Skip to content

Commit

Permalink
Merge pull request #197 from virtualeconomy/systemCall
Browse files Browse the repository at this point in the history
fix style issue also system transfer insufficient vsys issue
  • Loading branch information
ncying authored Apr 28, 2020
2 parents 1d88623 + 13b7f06 commit 601b285
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 23 deletions.
8 changes: 6 additions & 2 deletions src/main/scala/vsys/api/http/contract/ContractApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import vsys.blockchain.state.ByteStr
import vsys.blockchain.state.reader.StateReader
import vsys.blockchain.transaction._
import vsys.blockchain.UtxPool
import vsys.blockchain.contract.{ContractDepositWithdraw, ContractPermitted, ContractSystem}
import vsys.blockchain.contract._
import vsys.settings.RestAPISettings
import vsys.utils.serialization.Deser
import vsys.utils.Time
Expand Down Expand Up @@ -134,7 +134,11 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx
case ContractPermitted.contract.bytes => "TokenContractWithSplit"
case ContractPermitted.contractWithoutSplit.bytes => "TokenContract"
case ContractDepositWithdraw.contract.bytes => "DepositWithdrawContract"
case ContractDepositWithdrawProductive.contract.bytes => "ProductiveDepositWithdrawContract"
case ContractSystem.contract.bytes => "SystemContract"
case ContractLock.contract.bytes => "LockContract"
case ContractNonFungible.contract.bytes => "NonFungibleContract"
case ContractPaymentChannel.contract.bytes => "PaymentChannelContract"
case _ => "GeneralContract"
}

Expand Down Expand Up @@ -193,7 +197,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx
case Some(x) => (for {
acc <- Account.fromString(address)
} yield Json.obj(
"address/contract" -> acc.bytes.base58,
"address/contractId" -> acc.bytes.base58,
"height" -> height,
"tokenId" -> tokenIdStr,
"balance" -> state.tokenAccountBalance(ByteStr(tokenId.arr ++ acc.bytes.arr)),
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/vsys/blockchain/contract/ContractGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object ContractGen {
val loadSigner = Array(2.toByte, 1.toByte)
val loadCaller = Array(2.toByte, 2.toByte)
val loadTimestamp = Array(2.toByte, 3.toByte)
val loadTokenNum = Array(2.toByte, 4.toByte)
val loadLastTokenIndex = Array(2.toByte, 4.toByte)
val loadTransactionId = Array(2.toByte, 5.toByte)
val loadPublicKey = Array(2.toByte, 6.toByte)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ object ContractNonFungible {
assertCaller ++ Array(1.toByte),
basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(2.toByte),
tdbNewToken ++ Array(2.toByte, 2.toByte, 0.toByte),
loadTokenNum ++ Array(3.toByte),
loadLastTokenIndex ++ Array(3.toByte),
tdbaDeposit ++ Array(1.toByte, 2.toByte, 3.toByte))
lazy val issueFunc: Array[Byte] = getFunctionBytes(issueId, publicFuncType, nonReturnType, issueDataType, issueOpcs)
val issueFuncBytes: Array[Byte] = textualFunc("issue", Seq(), issuePara)
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/vsys/blockchain/state/StateWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class StateWriterImpl(p: StateStorage, synchronizationToken: ReentrantReadWriteL

measureSizeLog("contractNumDB")(blockDiff.txsDiff.contractNumDB) {
_.foreach { case (id, dValue) =>
val updatedNum = contractNumInfo(id) + dValue
val updatedNum = safeSum(contractNumInfo(id), dValue)
sp().contractNumDB.put(id, updatedNum)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package vsys.blockchain.state.diffs
import cats.implicits._
import vsys.blockchain.contract.ExecutionContext
import vsys.blockchain.state.opcdiffs.OpcFuncDiffer
import vsys.blockchain.state.reader.StateReader
import vsys.blockchain.state.reader.{CompositeStateReader, StateReader}
import vsys.blockchain.state.{Diff, LeaseInfo, Portfolio}
import vsys.blockchain.transaction.contract.ExecuteContractFunctionTransaction
import vsys.blockchain.transaction.{TransactionStatus, ValidationError}
Expand All @@ -18,6 +18,8 @@ object ExecuteContractFunctionTransactionDiff {
( for {
exContext <- ExecutionContext.fromExeConTx(s, settings, prevBlockTimestamp, currentBlockTimestamp, height, tx)
diff <- OpcFuncDiffer(exContext)(tx.data)
newState = new CompositeStateReader(s, diff.asBlockDiff(height, tx))
_ <- Either.cond(newState.accountPortfolio(senderAddress).balance >= tx.transactionFee, (), ValidationError.ContractVSYSBalanceInsufficient)
} yield Diff(
height = height,
tx = tx,
Expand Down
16 changes: 6 additions & 10 deletions src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,12 @@ object CDBVROpcDiff extends OpcDiffer {
Left(ContractLocalVariableIndexOutOfRange)
} else {
val combinedKey = context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes
if (DataType(stateMap(2)) == DataType.Amount) { // amount balance map
val getVal = context.state.contractNumInfo(ByteStr(combinedKey))
Right(dataStack.patch(pointer, Seq(DataEntry(Longs.toByteArray(getVal), DataType.Amount)), 1))
} else if (DataType(stateMap(2)) == DataType.Timestamp) { // timestamp
context.state.contractInfo(ByteStr(combinedKey)) match {
case Some(v) => Right(dataStack.patch(pointer, Seq(v), 1))
case _ => Right(dataStack.patch(pointer, Seq(DataEntry(Longs.toByteArray(0L), DataType.Timestamp)), 1))
}
} else {
Left(ContractStateMapNotDefined)
context.state.contractInfo(ByteStr(combinedKey)) match {
case Some(v) => Right(dataStack.patch(pointer, Seq(v), 1))
case _ if (DataType(stateMap(2)) == DataType.Timestamp) => Right(dataStack.patch(pointer, Seq(DataEntry(Longs.toByteArray(0L), DataType.Timestamp)), 1))
case _ if (DataType(stateMap(2)) == DataType.Amount) => Right(dataStack.patch(pointer,
Seq(DataEntry(Longs.toByteArray(context.state.contractNumInfo(ByteStr(combinedKey))), DataType.Amount)), 1))
case _ => Left(ContractStateMapNotDefined)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ object OpcDiff {
tokenDB = d.tokenDB,
tokenAccountBalance = d.tokenAccountBalance,
relatedAddress = d.relatedAddress,
portfolios = d.portfolios
portfolios = d.portfolios
)

def asBlockDiff(height: Int, tx: Transaction): BlockDiff =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ object TransactionStatus extends Enumeration {
val ContractStateMapNotDefined = Value(27)
val ContractMapValueInsufficient = Value(28)
val ContractInvalidSignature = Value(29)
val ContractVSYSBalanceInsufficient = Value(30)
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ object ValidationError {
case object ContractInvalidSignature extends ContractValidationError {
override val transactionStatus = TransactionStatus.ContractInvalidSignature
}
case object ContractVSYSBalanceInsufficient extends ContractValidationError {
override val transactionStatus = TransactionStatus.ContractVSYSBalanceInsufficient
}
case object EmptyProofs extends ValidationError
case class InvalidSignature(s: Signed, details: Option[InvalidSignature] = None) extends ValidationError
case class AccountBalanceError(errs: Map[Account, String]) extends ValidationError
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,16 +267,17 @@ class ExecuteTokenContractDiffTest extends PropSpec
}
}

val preconditionsAndExecuteContractSystemSend: Gen[(GenesisTransaction, ExecuteContractFunctionTransaction, Long, Address)] = for {
val preconditionsAndExecuteContractSystemSend: Gen[(GenesisTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Address)] = for {
(master, ts, fee) <- ContractGenHelper.basicContractTestGen()
genesis <- genesisTokenGen(master, ts)
recipient <- mintingAddressGen
description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize)
executeContractSystemSend <- sendVSYSGen(master, recipient, 100000L, description, fee, ts)
} yield (genesis, executeContractSystemSend, fee, recipient)
executeContractSystemSend2 <- sendVSYSGen(master, recipient, ENOUGH_AMT, description, fee, ts)
} yield (genesis, executeContractSystemSend, executeContractSystemSend2, fee, recipient)

property("execute contract transaction systemSend successfully") {
forAll(preconditionsAndExecuteContractSystemSend) { case (genesis, executeContractSystemSend: ExecuteContractFunctionTransaction, fee: Long, recipient) =>
forAll(preconditionsAndExecuteContractSystemSend) { case (genesis, executeContractSystemSend: ExecuteContractFunctionTransaction, _, fee: Long, recipient) =>
assertDiffAndState(Seq(TestBlock.create(Seq(genesis))), TestBlock.create(Seq(executeContractSystemSend))) { (blockDiff, newState) =>
val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values)
val sender = executeContractSystemSend.proofs.firstCurveProof.explicitGet().publicKey
Expand All @@ -292,4 +293,17 @@ class ExecuteTokenContractDiffTest extends PropSpec
}
}

property("execute contract transaction systemSend failed dual to insufficient VSYS") {
forAll(preconditionsAndExecuteContractSystemSend) { case (genesis, _, executeContractSystemSend2: ExecuteContractFunctionTransaction, fee: Long, recipient) =>
assertDiffEi(Seq(TestBlock.create(Seq(genesis))), TestBlock.createWithTxStatus(Seq(executeContractSystemSend2), TransactionStatus.ContractVSYSBalanceInsufficient)) { blockDiffEi =>
blockDiffEi shouldBe an[Right[_, _]]
val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiffEi.explicitGet().txsDiff.portfolios.values)
totalPortfolioDiff.balance shouldBe -fee
blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true
blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true
blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractVSYSBalanceInsufficient
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ class CommonValidationContractTest extends PropSpec
description <- validDescStringGen
genesis <- genesisTokenGen(master, ts)
recipient <- accountGen
transfer: PaymentTransaction <- paymentGeneratorP(master, recipient)
regTokenContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts + 1)
transfer: PaymentTransaction <- paymentGeneratorP(ts + 1, master, recipient)
regTokenContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts + 2)
pContract <- paymentChannelContract
sysTokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet()
dataForPaymentChannel: Seq[DataEntry] <- initPaymentChannelContractDataStackGen(sysTokenId.arr)
// Register a payment channel that supports VSYS
regPaymentChannel <- registerPaymentChannelGen(master, pContract, dataForPaymentChannel, description, fee + 10000000000L, ts + 2)
regPaymentChannel <- registerPaymentChannelGen(master, pContract, dataForPaymentChannel, description, fee + 10000000000L, ts + 3)
} yield (genesis, transfer, regTokenContract, regPaymentChannel)

property("disallows contract related tx before allowed height") {
Expand Down

0 comments on commit 601b285

Please sign in to comment.