From 7a38029eeae036a3620747b20734ed962ad0922e Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 5 Mar 2020 00:07:17 +0800 Subject: [PATCH 001/391] add atomic swap contract --- .../contract/ContractAtomicSwap.scala | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala diff --git a/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala new file mode 100644 index 000000000..706c9d213 --- /dev/null +++ b/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala @@ -0,0 +1,145 @@ +package vsys.blockchain.contract + +import com.google.common.primitives.Ints +import vsys.blockchain.contract.ContractGen._ +import vsys.utils.serialization.Deser + +object ContractAtomicSwap { + lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(initTrigger, depositTrigger, withdrawTrigger), + Seq(lockFunc, solvePuzzleFunc, expireWithdrawFunc), + Seq(makerStateVar.arr, tokenIdStateVar.arr), + Seq(balanceMap.arr, swapOwnerMap.arr, swapRecipientMap.arr, + swapPuzzleMap.arr, swapAmountMap.arr, swapExpiredTimeMap.arr, swapStatusMap.arr), + Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual) + ).right.get + + // State Var + val stateVarName = List("maker", "tokenId") + val makerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) + val tokenIdStateVar: StateVar = StateVar(1.toByte, DataType.TokenId.id.toByte) + lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) + + // State Map + val stateMapName = List("balance", "swapOwner", "swapRecipient", "swapPuzzle", "swapAmount", "swapExpiredTime", "swapStatus") + val balanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val swapOwnerMap: StateMap = StateMap(1.toByte, DataType.ShortText.id.toByte, DataType.Address.id.toByte) + val swapRecipientMap: StateMap = StateMap(2.toByte, DataType.ShortText.id.toByte, DataType.Address.id.toByte) + val swapPuzzleMap: StateMap = StateMap(3.toByte, DataType.ShortText.id.toByte, DataType.ShortText.id.toByte) + val swapAmountMap: StateMap = StateMap(4.toByte, DataType.ShortText.id.toByte, DataType.Amount.id.toByte) + val swapExpiredTimeMap: StateMap = StateMap(5.toByte, DataType.ShortText.id.toByte, DataType.Timestamp.id.toByte) + val swapStatusMap: StateMap = StateMap(6.toByte, DataType.ShortText.id.toByte, DataType.Boolean.id.toByte) + lazy val stateMapTextual: Array[Byte] = Deser.serializeArrays(stateMapName.map(x => Deser.serilizeString(x))) + + // Initialization Trigger + val initId: Short = 0 + val initPara: Seq[String] = Seq("tokenId", + "signer") + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte) + val initTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(1.toByte), + cdbvSet ++ Array(makerStateVar.index, 1.toByte), + cdbvSet ++ Array(tokenIdStateVar.index, 0.toByte) + ) + lazy val initTrigger: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initTriggerOpcs) + val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) + + // Deposit Trigger + val depositId: Short = 1 + val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId", + "contractTokenId") + val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val depositTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(tokenIdStateVar.index, 3.toByte), + assertEqual ++ Array(2.toByte, 3.toByte), + cdbvMapValAdd ++ Array(balanceMap.index, 0.toByte, 1.toByte) + ) + lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) + val depositTextualBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) + + // WithDraw Trigger + val withdrawId: Short = 2 + val withdrawPara: Seq[String] = Seq("withdrawer", "amount", "tokenId", + "contractTokenId") + val withdrawDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val withdrawTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(tokenIdStateVar.index, 3.toByte), + assertEqual ++ Array(2.toByte, 3.toByte), + cdbvMapValMinus ++ Array(balanceMap.index, 0.toByte, 1.toByte) + ) + lazy val withdrawTrigger: Array[Byte] = getFunctionBytes(withdrawId, onWithDrawTriggerType, nonReturnType, withdrawDataType, withdrawTriggerOpcs) + val withdrawTextualBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) + + // Lock Function + val lockId: Short = 0 + val lockPara: Seq[String] = Seq("amount", "recipient", "puzzle", "expiredTime", + "caller", "txId", "valueTrue") + val lockDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Address.id.toByte, DataType.ShortText.id.toByte, DataType.Timestamp.id.toByte) + val lockFunctionOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(4.toByte), + cdbvMapValMinus ++ Array(balanceMap.index, 4.toByte, 0.toByte), + loadTransactionId ++ Array(5.toByte), + cdbvMapSet ++ Array(swapOwnerMap.index, 5.toByte, 4.toByte), + cdbvMapSet ++ Array(swapRecipientMap.index, 5.toByte, 1.toByte), + cdbvMapSet ++ Array(swapPuzzleMap.index, 5.toByte, 2.toByte), + cdbvMapSet ++ Array(swapAmountMap.index, 5.toByte, 0.toByte), + cdbvMapSet ++ Array(swapExpiredTimeMap.index, 5.toByte, 3.toByte), + cdbvrConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + cdbvMapSet ++ Array(swapStatusMap.index, 5.toByte, 6.toByte) + ) + lazy val lockFunc: Array[Byte] = getFunctionBytes(lockId, publicFuncType, nonReturnType, lockDataType, lockFunctionOpcs) + val lockTextualBytes: Array[Byte] = textualFunc("lock", Seq(), lockPara) + + // Solve Puzzle Function + val solvePuzzleId: Short = 1 + val solvePuzzlePara: Seq[String] = Seq("txId", "key", + "status", "recipient", "currentTime", "expiredTime", "res", "puzzle", "amount", "valueFalse") + val solvePuzzleDataType: Array[Byte] = Array(DataType.ShortText.id.toByte, DataType.ShortText.id.toByte) + val solvePuzzleFunctionOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(swapStatusMap.index, 0.toByte, 2.toByte), + assertTrue ++ Array(2.toByte), + cdbvrMapGet ++ Array(swapRecipientMap.index, 0.toByte, 3.toByte), + assertCaller ++ Array(3.toByte), + loadTimestamp ++ Array(4.toByte), + cdbvrMapGet ++ Array(swapExpiredTimeMap.index, 0.toByte, 5.toByte), + compareGreater ++ Array(5.toByte, 4.toByte, 6.toByte), + assertTrue ++ Array(6.toByte), + cdbvrMapGet ++ Array(swapPuzzleMap.index, 0.toByte, 7.toByte), + assertHash ++ Array(7.toByte, 1.toByte), + cdbvrMapGet ++ Array(swapAmountMap.index, 0.toByte, 8.toByte), + cdbvrConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(9.toByte), + cdbvMapSet ++ Array(swapStatusMap.index, 0.toByte, 9.toByte), + cdbvMapValAdd ++ Array(balanceMap.index, 3.toByte, 8.toByte) + ) + lazy val solvePuzzleFunc: Array[Byte] = getFunctionBytes(solvePuzzleId, publicFuncType, nonReturnType, solvePuzzleDataType, solvePuzzleFunctionOpcs) + val solvePuzzleTextualBytes: Array[Byte] = textualFunc("solvePuzzle", Seq(), solvePuzzlePara) + + // Expire Withdraw Function + val expireWithdrawId: Short = 2 + val expireWithdrawPara: Seq[String] = Seq("txId", + "status", "owner", "currentTime", "expiredTime", "res", "amount", "valueFalse") + val expireWithdrawDataType: Array[Byte] = Array(DataType.ShortText.id.toByte) + val expireWithdrawFunctionOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(swapStatusMap.index, 0.toByte, 1.toByte), + assertTrue ++ Array(1.toByte), + cdbvrMapGet ++ Array(swapOwnerMap.index, 0.toByte, 2.toByte), + assertCaller ++ Array(2.toByte), + loadTimestamp ++ Array(3.toByte), + cdbvrMapGet ++ Array(swapExpiredTimeMap.index, 0.toByte, 4.toByte), + compareGreater ++ Array(3.toByte, 4.toByte, 5.toByte), + assertTrue ++ Array(5.toByte), + cdbvrMapGet ++ Array(swapAmountMap.index, 0.toByte, 6.toByte), + cdbvrConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + cdbvMapSet ++ Array(swapStatusMap.index, 0.toByte, 7.toByte), + cdbvMapValAdd ++ Array(balanceMap.index, 2.toByte, 6.toByte) + ) + lazy val expireWithdrawFunc: Array[Byte] = getFunctionBytes(expireWithdrawId, publicFuncType, nonReturnType, expireWithdrawDataType, expireWithdrawFunctionOpcs) + val expireWithdrawTextualBytes: Array[Byte] = textualFunc("expireWithdraw", Seq(), expireWithdrawPara) + + // Gen Textual + lazy val triggerTextual: Array[Byte] = Deser.serializeArrays(Seq(initTextualBytes, depositTextualBytes, withdrawTextualBytes)) + lazy val descriptorTextual: Array[Byte] = Deser.serializeArrays(Seq(lockTextualBytes, solvePuzzleTextualBytes, expireWithdrawTextualBytes)) + +} \ No newline at end of file From ee999c37edbf9e0896915e752485d28c919a1221 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Jun 2020 09:59:55 +0800 Subject: [PATCH 002/391] update opc --- .../scala/vsys/blockchain/contract/ContractAtomicSwap.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala index 706c9d213..7516fd3fc 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala @@ -86,7 +86,7 @@ object ContractAtomicSwap { cdbvMapSet ++ Array(swapPuzzleMap.index, 5.toByte, 2.toByte), cdbvMapSet ++ Array(swapAmountMap.index, 5.toByte, 0.toByte), cdbvMapSet ++ Array(swapExpiredTimeMap.index, 5.toByte, 3.toByte), - cdbvrConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), cdbvMapSet ++ Array(swapStatusMap.index, 5.toByte, 6.toByte) ) lazy val lockFunc: Array[Byte] = getFunctionBytes(lockId, publicFuncType, nonReturnType, lockDataType, lockFunctionOpcs) @@ -109,7 +109,7 @@ object ContractAtomicSwap { cdbvrMapGet ++ Array(swapPuzzleMap.index, 0.toByte, 7.toByte), assertHash ++ Array(7.toByte, 1.toByte), cdbvrMapGet ++ Array(swapAmountMap.index, 0.toByte, 8.toByte), - cdbvrConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(9.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(9.toByte), cdbvMapSet ++ Array(swapStatusMap.index, 0.toByte, 9.toByte), cdbvMapValAdd ++ Array(balanceMap.index, 3.toByte, 8.toByte) ) @@ -131,7 +131,7 @@ object ContractAtomicSwap { compareGreater ++ Array(3.toByte, 4.toByte, 5.toByte), assertTrue ++ Array(5.toByte), cdbvrMapGet ++ Array(swapAmountMap.index, 0.toByte, 6.toByte), - cdbvrConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), cdbvMapSet ++ Array(swapStatusMap.index, 0.toByte, 7.toByte), cdbvMapValAdd ++ Array(balanceMap.index, 2.toByte, 6.toByte) ) From 6b3cd8ea7dbe5e0ea84ab353ff934ed3102366a2 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Jun 2020 10:00:12 +0800 Subject: [PATCH 003/391] fix typo --- src/test/scala/tools/ContractTranslator.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/scala/tools/ContractTranslator.scala b/src/test/scala/tools/ContractTranslator.scala index a917483be..105a10ca3 100644 --- a/src/test/scala/tools/ContractTranslator.scala +++ b/src/test/scala/tools/ContractTranslator.scala @@ -21,7 +21,7 @@ import vsys.utils.serialization.Deser import scala.util.{Failure, Success, Try} object ContractTranslator extends App { - val bytes = ContractPaymentChannel.contract.bytes.arr + val bytes = ContractAtomicSwap.contract.bytes.arr println(Base58.encode(bytes)) print("Contract Bytes Length:") @@ -168,7 +168,7 @@ object ContractTranslator extends App { } def printTextual(t: Try[(Seq[Seq[String]], Seq[Seq[String]], Seq[String], Seq[Seq[String]])]): Unit = { - if (t.isFailure) println("Invalid Texture") + if (t.isFailure) println("Invalid Textural") else { val r = t.get val (trig, desc, stav, stam) = r From e44dc7db9e301621a1e6d30e3cef9ebfcaa4d821 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Jun 2020 10:01:55 +0800 Subject: [PATCH 004/391] update state map textual --- .../vsys/blockchain/contract/ContractAtomicSwap.scala | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala index 7516fd3fc..3eeb2e33a 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala @@ -21,7 +21,13 @@ object ContractAtomicSwap { lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map - val stateMapName = List("balance", "swapOwner", "swapRecipient", "swapPuzzle", "swapAmount", "swapExpiredTime", "swapStatus") + val stateMapBalance = List("contractBalance", "userAddress", "balance") + val stateMapOwner = List("swapOwner", "swapId", "owner") + val stateMapRecipient = List("swapRecipient", "swapId", "recipient") + val stateMapPuzzle = List("swapPuzzle", "swapId", "puzzle") + val stateMapAmount = List("swapAmount", "swapId", "amount") + val stateMapExpiredTime = List("swapExpiredTime", "swapId", "expiredTime") + val stateMapStatus = List("swapStatus", "swapId", "status") val balanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) val swapOwnerMap: StateMap = StateMap(1.toByte, DataType.ShortText.id.toByte, DataType.Address.id.toByte) val swapRecipientMap: StateMap = StateMap(2.toByte, DataType.ShortText.id.toByte, DataType.Address.id.toByte) @@ -29,7 +35,8 @@ object ContractAtomicSwap { val swapAmountMap: StateMap = StateMap(4.toByte, DataType.ShortText.id.toByte, DataType.Amount.id.toByte) val swapExpiredTimeMap: StateMap = StateMap(5.toByte, DataType.ShortText.id.toByte, DataType.Timestamp.id.toByte) val swapStatusMap: StateMap = StateMap(6.toByte, DataType.ShortText.id.toByte, DataType.Boolean.id.toByte) - lazy val stateMapTextual: Array[Byte] = Deser.serializeArrays(stateMapName.map(x => Deser.serilizeString(x))) + lazy val stateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapBalance, stateMapOwner, stateMapRecipient, stateMapPuzzle, + stateMapAmount, stateMapExpiredTime, stateMapStatus)) // Initialization Trigger val initId: Short = 0 From 79cd84ba138be78e845ec91f3799eecb6f88bb20 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 23 Jun 2020 10:16:12 +0800 Subject: [PATCH 005/391] update data entry type --- .../contract/ContractAtomicSwap.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala index 3eeb2e33a..f2fbb7166 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractAtomicSwap.scala @@ -29,12 +29,12 @@ object ContractAtomicSwap { val stateMapExpiredTime = List("swapExpiredTime", "swapId", "expiredTime") val stateMapStatus = List("swapStatus", "swapId", "status") val balanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) - val swapOwnerMap: StateMap = StateMap(1.toByte, DataType.ShortText.id.toByte, DataType.Address.id.toByte) - val swapRecipientMap: StateMap = StateMap(2.toByte, DataType.ShortText.id.toByte, DataType.Address.id.toByte) - val swapPuzzleMap: StateMap = StateMap(3.toByte, DataType.ShortText.id.toByte, DataType.ShortText.id.toByte) - val swapAmountMap: StateMap = StateMap(4.toByte, DataType.ShortText.id.toByte, DataType.Amount.id.toByte) - val swapExpiredTimeMap: StateMap = StateMap(5.toByte, DataType.ShortText.id.toByte, DataType.Timestamp.id.toByte) - val swapStatusMap: StateMap = StateMap(6.toByte, DataType.ShortText.id.toByte, DataType.Boolean.id.toByte) + val swapOwnerMap: StateMap = StateMap(1.toByte, DataType.ShortBytes.id.toByte, DataType.Address.id.toByte) + val swapRecipientMap: StateMap = StateMap(2.toByte, DataType.ShortBytes.id.toByte, DataType.Address.id.toByte) + val swapPuzzleMap: StateMap = StateMap(3.toByte, DataType.ShortBytes.id.toByte, DataType.ShortBytes.id.toByte) + val swapAmountMap: StateMap = StateMap(4.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val swapExpiredTimeMap: StateMap = StateMap(5.toByte, DataType.ShortBytes.id.toByte, DataType.Timestamp.id.toByte) + val swapStatusMap: StateMap = StateMap(6.toByte, DataType.ShortBytes.id.toByte, DataType.Boolean.id.toByte) lazy val stateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapBalance, stateMapOwner, stateMapRecipient, stateMapPuzzle, stateMapAmount, stateMapExpiredTime, stateMapStatus)) @@ -83,7 +83,7 @@ object ContractAtomicSwap { val lockId: Short = 0 val lockPara: Seq[String] = Seq("amount", "recipient", "puzzle", "expiredTime", "caller", "txId", "valueTrue") - val lockDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Address.id.toByte, DataType.ShortText.id.toByte, DataType.Timestamp.id.toByte) + val lockDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Address.id.toByte, DataType.ShortBytes.id.toByte, DataType.Timestamp.id.toByte) val lockFunctionOpcs: Seq[Array[Byte]] = Seq( loadCaller ++ Array(4.toByte), cdbvMapValMinus ++ Array(balanceMap.index, 4.toByte, 0.toByte), @@ -103,7 +103,7 @@ object ContractAtomicSwap { val solvePuzzleId: Short = 1 val solvePuzzlePara: Seq[String] = Seq("txId", "key", "status", "recipient", "currentTime", "expiredTime", "res", "puzzle", "amount", "valueFalse") - val solvePuzzleDataType: Array[Byte] = Array(DataType.ShortText.id.toByte, DataType.ShortText.id.toByte) + val solvePuzzleDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.ShortBytes.id.toByte) val solvePuzzleFunctionOpcs: Seq[Array[Byte]] = Seq( cdbvrMapGet ++ Array(swapStatusMap.index, 0.toByte, 2.toByte), assertTrue ++ Array(2.toByte), @@ -127,7 +127,7 @@ object ContractAtomicSwap { val expireWithdrawId: Short = 2 val expireWithdrawPara: Seq[String] = Seq("txId", "status", "owner", "currentTime", "expiredTime", "res", "amount", "valueFalse") - val expireWithdrawDataType: Array[Byte] = Array(DataType.ShortText.id.toByte) + val expireWithdrawDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) val expireWithdrawFunctionOpcs: Seq[Array[Byte]] = Seq( cdbvrMapGet ++ Array(swapStatusMap.index, 0.toByte, 1.toByte), assertTrue ++ Array(1.toByte), From e9c57b66bd0dd08759b0106b723478a6ba1b5da2 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 23 Jun 2020 10:19:56 +0800 Subject: [PATCH 006/391] allow atomic swap contract --- src/main/scala/vsys/blockchain/contract/Contract.scala | 3 ++- .../scala/vsys/blockchain/state/diffs/CommonValidation.scala | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index 61d81eb19..9e1a3163a 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -144,7 +144,8 @@ object Contract extends ScorexLogging { !(bytes sameElements ContractPermitted.contractWithoutSplit.bytes.arr) && !(bytes sameElements ContractLock.contract.bytes.arr) && !(bytes sameElements ContractNonFungible.contract.bytes.arr) && - !(bytes sameElements ContractPaymentChannel.contract.bytes.arr)) { + !(bytes sameElements ContractPaymentChannel.contract.bytes.arr) && + !(bytes sameElements ContractAtomicSwap.contract.bytes.arr)){ log.warn(s"Illegal contract ${bytes.mkString(" ")}") false } else if (textualStr.isFailure || diff --git a/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala b/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala index 01b206a42..303eba420 100644 --- a/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala +++ b/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala @@ -45,7 +45,8 @@ object CommonValidation { else if (h <= settings.allowDepositWithdrawContractAfterHeight && (c == ContractLock.contract || c == ContractNonFungible.contract || - c == ContractPaymentChannel.contract)) + c == ContractPaymentChannel.contract || + c == ContractAtomicSwap.contract)) Left(GenericError(s"deposit withdraw contracts must not appear before height=${settings.allowDepositWithdrawContractAfterHeight}")) else Right(tx) } From 995e7db3d3466782c6bc9268dd10107e2dde4be1 Mon Sep 17 00:00:00 2001 From: zl730 Date: Wed, 24 Jun 2020 17:54:52 +0800 Subject: [PATCH 007/391] add opcblock datatype --- .../vsys/blockchain/contract/DataEntry.scala | 73 +++++++------------ .../vsys/blockchain/contract/DataType.scala | 45 +++++++----- 2 files changed, 52 insertions(+), 66 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index d84ebbabe..8cea787cb 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -6,7 +6,6 @@ import scorex.crypto.encode.Base58 import vsys.account.{Address, AddressScheme, ContractAccount, PublicKeyAccount} import vsys.account.ContractAccount.ChecksumLength import vsys.blockchain.state.ByteStr -import vsys.blockchain.transaction.TransactionParser.{AmountLength, KeyLength, TimestampLength} import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError.InvalidDataEntry import vsys.utils.crypto.hash.SecureCryptographicHash._ @@ -14,7 +13,7 @@ import vsys.utils.crypto.hash.SecureCryptographicHash._ import scala.util.Success case class DataEntry(data: Array[Byte], - dataType: DataType.Value) { + dataType: DataType.DataTypeVal) { lazy val bytes: Array[Byte] = Array(dataType.id.asInstanceOf[Byte]) ++ data @@ -23,7 +22,7 @@ case class DataEntry(data: Array[Byte], "type" -> dataType ) - private def toJson(d: Array[Byte], t: DataType.Value): JsValue = { + private def toJson(d: Array[Byte], t: DataType.DataTypeVal): JsValue = { t match { case DataType.PublicKey => Json.toJson(PublicKeyAccount(d).address) case DataType.Address => Json.toJson(Address.fromBytes(d).right.get.address) @@ -35,6 +34,8 @@ case class DataEntry(data: Array[Byte], case DataType.Timestamp => Json.toJson(Longs.fromByteArray(d)) case DataType.Boolean => Json.toJson(if (d(0) == 1.toByte) "True" else "False") case DataType.ShortBytes => Json.toJson(Base58.encode(d)) + case DataType.OpcBlock => Json.toJson("Internal code block") + case _ => Json.toJson("Unsupported data type") } } @@ -51,10 +52,7 @@ object DataEntry { private lazy val scheme = AddressScheme.current.value - val maxShortTextLength = 140 - val maxShortBytesLength = 255 - - def create(data: Array[Byte], dataType: DataType.Value): Either[ValidationError, DataEntry] = { + def create(data: Array[Byte], dataType: DataType.DataTypeVal): Either[ValidationError, DataEntry] = { dataType match { case DataType.ShortText if checkDataType(Shorts.toByteArray(data.length.toShort) ++ data, dataType) => Right(DataEntry(Shorts.toByteArray(data.length.toShort) ++ data, dataType)) case DataType.ShortBytes if checkDataType(Shorts.toByteArray(data.length.toShort) ++ data, dataType) => Right(DataEntry(Shorts.toByteArray(data.length.toShort) ++ data, dataType)) @@ -68,9 +66,9 @@ object DataEntry { Left(InvalidDataEntry) else DataType.fromByte(bytes(0)) match { - case Some(DataType.ShortText) => create(bytes.slice(3, bytes.length), DataType(bytes(0))) - case Some(DataType.ShortBytes) => create(bytes.slice(3, bytes.length), DataType(bytes(0))) - case _ => create(bytes.tail, DataType(bytes(0))) + case Some(DataType.ShortText) => create(bytes.drop(3), DataType.ShortText) + case Some(DataType.ShortBytes) => create(bytes.drop(3), DataType.ShortBytes) + case _ => create(bytes.tail, DataType(bytes(0)).asInstanceOf[DataType.DataTypeVal]) } } @@ -81,28 +79,12 @@ object DataEntry { } } - def parseArraySize(bytes: Array[Byte], position: Int): Either[ValidationError, (DataEntry, Int)] = { - DataType.fromByte(bytes(position)) match { - case Some(DataType.PublicKey) if checkDataType(bytes.slice(position + 1, position + 1 + KeyLength), DataType.PublicKey) => - Right((DataEntry(bytes.slice(position + 1, position + 1 + KeyLength), DataType.PublicKey), position + 1 + KeyLength)) - case Some(DataType.Address) if checkDataType(bytes.slice(position + 1, position + 1 + Address.AddressLength), DataType.Address) => - Right((DataEntry(bytes.slice(position + 1, position + 1 + Address.AddressLength), DataType.Address), position + 1 + Address.AddressLength)) - case Some(DataType.Amount) if checkDataType(bytes.slice(position + 1, position + 1 + AmountLength), DataType.Amount) => - Right((DataEntry(bytes.slice(position + 1, position + 1 + AmountLength), DataType.Amount), position + 1 + AmountLength)) - case Some(DataType.Int32) if checkDataType(bytes.slice(position + 1, position + 1 + 4), DataType.Int32) => - Right((DataEntry(bytes.slice(position + 1, position + 1 + 4), DataType.Int32), position + 1 + 4)) - case Some(DataType.ShortText) if checkDataType(bytes.slice(position + 1, position + 3 + Shorts.fromByteArray(bytes.slice(position + 1, position + 3))), DataType.ShortText) => - Right((DataEntry(bytes.slice(position + 1, position + 3 + Shorts.fromByteArray(bytes.slice(position + 1, position + 3))), DataType.ShortText), position + 3 + Shorts.fromByteArray(bytes.slice(position + 1, position + 3)))) - case Some(DataType.ContractAccount) if checkDataType(bytes.slice(position + 1, position + 1 + ContractAccount.AddressLength), DataType.ContractAccount) => - Right((DataEntry(bytes.slice(position + 1, position + 1 + ContractAccount.AddressLength), DataType.ContractAccount), position + 1 + ContractAccount.AddressLength)) - case Some(DataType.TokenId) if checkDataType(bytes.slice(position + 1, position + 1 + ContractAccount.TokenAddressLength), DataType.TokenId) => - Right((DataEntry(bytes.slice(position + 1, position + 1 + ContractAccount.TokenAddressLength), DataType.TokenId), position + 1 + ContractAccount.TokenAddressLength)) - case Some(DataType.Timestamp) if checkDataType(bytes.slice(position + 1, position + 1 + TimestampLength), DataType.Timestamp) => - Right((DataEntry(bytes.slice(position + 1, position + 1 + TimestampLength), DataType.Timestamp), position + 1 + TimestampLength)) - case Some(DataType.Boolean) if checkDataType(bytes.slice(position + 1, position + 1 + 1), DataType.Boolean) => - Right((DataEntry(bytes.slice(position + 1, position + 1 + 1), DataType.Boolean), position + 1 + 1)) - case Some(DataType.ShortBytes) if checkDataType(bytes.slice(position + 1, position + 3 + Shorts.fromByteArray(bytes.slice(position + 1, position + 3))), DataType.ShortBytes) => - Right((DataEntry(bytes.slice(position + 1, position + 3 + Shorts.fromByteArray(bytes.slice(position + 1, position + 3))), DataType.ShortBytes), position + 3 + Shorts.fromByteArray(bytes.slice(position + 1, position + 3)))) + private def parseArray(bytes: Array[Byte]): Either[ValidationError, (DataEntry, Array[Byte])] = { + DataType.fromByte(bytes(0)) match { + case Some(dt: DataType.DataTypeVal) if (dt.lenFixed && checkDataType(bytes.drop(1).take(dt.maxLen), dt)) => + Right((DataEntry(bytes.drop(1).take(dt.maxLen), dt), bytes.drop(1 + dt.maxLen))) + case Some(dt: DataType.DataTypeVal) if (dt.maxLen <= Short.MaxValue && checkDataType(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt)) => + Right((DataEntry(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt), bytes.drop(3 + Shorts.fromByteArray(bytes.drop(1).take(2))))) case _ => Left(InvalidDataEntry) } } @@ -111,35 +93,32 @@ object DataEntry { Shorts.toByteArray(ds.length.toShort) ++ Bytes.concat(ds.map(_.bytes): _*) } - def right(structure: (Seq[DataEntry], Int)): Either[ValidationError, (Seq[DataEntry], Int)] = Right(structure) - def parseArrays(bytes: Array[Byte]): Either[ValidationError, Seq[DataEntry]] = { - val length = Shorts.fromByteArray(bytes.slice(0, 2)) - (0 until length).foldLeft(right((Seq.empty[DataEntry], 2))) { - case (accPos, _) => accPos.flatMap(ap => parseArraySize(bytes, ap._2) match { + val length = Shorts.fromByteArray(bytes.take(2)) + (0 until length).foldLeft(Right((Seq.empty[DataEntry], bytes.drop(2))): Either[ValidationError, (Seq[DataEntry], Array[Byte])]) { + case (accPos, _) => accPos.flatMap(ap => parseArray(ap._2) match { case Right((arr, nextPos)) => Right((ap._1 :+ arr, nextPos)) case Left(l) => Left(l) }) - } match { case Right((acc, _)) => Right(acc) case Left(l) => Left(l) } } - private def checkDataType(data: Array[Byte], dataType: DataType.Value): Boolean = dataType match { - case DataType.PublicKey => data.length == KeyLength + private def checkDataType(data: Array[Byte], dataType: DataType.DataTypeVal): Boolean = + ((dataType.lenFixed && data.length == dataType.maxLen) + || (!dataType.lenFixed && Shorts.fromByteArray(data.take(2)) == data.drop(2).length && data.drop(2).length <= dataType.maxLen)) && + (dataType match { case DataType.Address => Address.fromBytes(data).isRight - case DataType.Amount => data.length == AmountLength && Longs.fromByteArray(data) >= 0 - case DataType.Int32 => data.length == 4 && Ints.fromByteArray(data) >= 0 - case DataType.ShortText => Shorts.fromByteArray(data.slice(0, 2)) + 2 == data.length && data.length <= 2 + maxShortTextLength + case DataType.Amount => Longs.fromByteArray(data) >= 0 + case DataType.Int32 => Ints.fromByteArray(data) >= 0 case DataType.ContractAccount => ContractAccount.fromBytes(data).isRight case DataType.TokenId => isTokenIdValid(data) - case DataType.Timestamp => data.length == TimestampLength - case DataType.Boolean => data.length == 1 && (data(0) == 1.toByte || data(0) == 0.toByte) - case DataType.ShortBytes => Shorts.fromByteArray(data.slice(0, 2)) + 2 == data.length && data.length <= 2 + maxShortBytesLength + case DataType.Boolean => (data(0) == 1.toByte || data(0) == 0.toByte) + case DataType.PublicKey | DataType.ShortText | DataType.Timestamp | DataType.ShortBytes | DataType.OpcBlock => true case _ => false - } + }) private def isTokenIdValid(addressBytes: Array[Byte]): Boolean = { val version = addressBytes.head diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index 4b13ff4b6..3cb385205 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -1,26 +1,33 @@ package vsys.blockchain.contract +import vsys.blockchain.transaction.TransactionParser.{AmountLength, KeyLength, TimestampLength} + +import scala.util.Try + object DataType extends Enumeration { - val PublicKey = Value(1) - val Address = Value(2) - val Amount = Value(3) - val Int32 = Value(4) - val ShortText = Value(5) - val ContractAccount = Value(6) - val Account = Value(7) - val TokenId = Value(8) - val Timestamp = Value(9) - val Boolean = Value(10) - val ShortBytes = Value(11) - val Balance = Value(12) - - def fromByte(b: Byte): Option[DataType.Value] = { - if (b < DataType.PublicKey.id || b > DataType.ShortBytes.id) - None - else - Some(DataType(b)) - } + val MaxShortTextLength = 140 + val MaxShortBytesLength = 255 + val MaxOpcBlockLength = 255 + + sealed case class DataTypeVal(dataType: Int, lenFixed: Boolean, maxLen: Int) extends Val(dataType) { def *(n: Int): Int = n * dataType } + + val PublicKey = DataTypeVal(1, true, KeyLength) + val Address = DataTypeVal(2, true, vsys.account.Address.AddressLength) + val Amount = DataTypeVal(3, true, AmountLength) + val Int32 = DataTypeVal(4, true, 4) + val ShortText = DataTypeVal(5, false, MaxShortTextLength) + val ContractAccount = DataTypeVal(6, true, vsys.account.ContractAccount.AddressLength) + val Account = DataTypeVal(7, false, (vsys.account.Address.AddressLength).max(vsys.account.ContractAccount.AddressLength)) + val TokenId = DataTypeVal(8, true, vsys.account.ContractAccount.TokenAddressLength) + val Timestamp = DataTypeVal(9, true, TimestampLength) + val Boolean = DataTypeVal(10, true, 1) + val ShortBytes = DataTypeVal(11, false, MaxShortBytesLength) + val Balance = DataTypeVal(12, true, AmountLength) + val OpcBlock = DataTypeVal(13, false, MaxOpcBlockLength) + + def fromByte(b: Byte): Option[DataType.DataTypeVal] = Try(DataType(b).asInstanceOf[DataTypeVal]).toOption + private def check(a: Byte, b: Byte): Boolean = { if (a == b) true else if (a == DataType.Account.id) b == DataType.Address.id || b == DataType.ContractAccount.id From 6d9ee2d3168ee3092d90a2e7d4f63c1c57d93788 Mon Sep 17 00:00:00 2001 From: zl730 Date: Wed, 24 Jun 2020 17:55:41 +0800 Subject: [PATCH 008/391] fix usage --- src/main/scala/vsys/blockchain/contract/Contract.scala | 4 ++-- .../scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index 61d81eb19..6ea65e947 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -132,10 +132,10 @@ object Contract extends ScorexLogging { } } - def checkStateVar(stateVar: Array[Byte], dataType: DataType.Value): Boolean = + def checkStateVar(stateVar: Array[Byte], dataType: DataType.DataTypeVal): Boolean = stateVar.length == 2 && dataType == DataType(stateVar(1)) - def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.Value, valueDataType: DataType.Value): Boolean = + def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.DataTypeVal, valueDataType: DataType.DataTypeVal): Boolean = stateMap.length == 3 && keyDataType == DataType(stateMap(1)) && valueDataType == DataType(stateMap(2)) private def isByteArrayValid(bytes: Array[Byte], textual: Seq[Array[Byte]]): Boolean = { diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala index 3d92b1627..0f58853c0 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala @@ -13,7 +13,7 @@ object CDBVROpcDiff extends OpcDiffer { def get(context: ExecutionContext)(stateVar: Array[Byte], dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateVar(stateVar, DataType(stateVar(1)))) { + if (!checkStateVar(stateVar, DataType(stateVar(1)).asInstanceOf[DataType.DataTypeVal])) { Left(ContractInvalidStateVariable) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) @@ -27,7 +27,7 @@ object CDBVROpcDiff extends OpcDiffer { def mapGet(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)))) { + if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)).asInstanceOf[DataType.DataTypeVal])) { Left(ContractInvalidStateMap) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) @@ -42,7 +42,7 @@ object CDBVROpcDiff extends OpcDiffer { def mapGetOrDefault(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)))) { + if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)).asInstanceOf[DataType.DataTypeVal])) { Left(ContractInvalidStateMap) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) From cc38904ac24fbedb024e8920ead708f63d87ff76 Mon Sep 17 00:00:00 2001 From: zl730 Date: Wed, 24 Jun 2020 17:56:08 +0800 Subject: [PATCH 009/391] add if opc --- .../blockchain/state/opcdiffs/IfOpcDiff.scala | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala new file mode 100644 index 000000000..774d7636a --- /dev/null +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala @@ -0,0 +1,65 @@ +package vsys.blockchain.state.opcdiffs + +import cats.implicits._ +import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.reader.CompositeStateReader +import vsys.blockchain.transaction.ValidationError +import vsys.blockchain.transaction.ValidationError._ +import vsys.utils.serialization.Deser + +import scala.util.{Left, Right, Try, Failure, Success} + +object IfOpcDiff extends OpcDiffer { + + def executeOpcBlock(context: ExecutionContext, opcBlock: DataEntry, dataStack: Seq[DataEntry]): Either[ValidationError, (OpcDiff, Seq[DataEntry])] = { + opcBlock.dataType match { + case DataType.OpcBlock => { + Try(Deser.parseArrays(opcBlock.data)) match { + case Success(opclines) => { + opclines.foldLeft(Right((OpcDiff.empty, dataStack)): Either[ValidationError, (OpcDiff, Seq[DataEntry])]) { + case (acc, opc) => acc.flatMap { case (oldDiff, oldData) => { + val oldState = new CompositeStateReader(context.state, oldDiff.asBlockDiff(context.height, context.transaction)) + OpcDiffer(context.copy(state = oldState))(opc, oldData) map { case (opcDiff, newData) => (oldDiff.combine(opcDiff), newData) } + }} + } + } + case Failure(_) => Left(ContractInvalidOPCData) + } + } + case _ => Left(ContractDataTypeMismatch) + } + } + + def runCondition(cond: DataEntry): Either[ValidationError, Boolean] = { + cond.dataType match { + case DataType.Boolean => Right(cond.data sameElements Array(1.toByte)) + case _ => Left(ContractDataTypeMismatch) + } + } + + object IfType extends Enumeration(1) { + val If, IfElse = Value + } + + override def parseBytesDf(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, OpcDiff] = + throw new UnsupportedOperationException(s"Could not be reached method") + + override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = + throw new UnsupportedOperationException(s"Could not be reached method") + + override def parseBytes(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, (OpcDiff, Seq[DataEntry])] = + (bytes.headOption.flatMap(f => Try(IfType(f)).toOption), bytes.length) match { + case (Some(IfType.If), 3) if checkData(bytes, data.length, 2, false) => { + runCondition(data(bytes(1))).flatMap(cond => + if(cond) executeOpcBlock(context, data(bytes(2)), data) + else Right((OpcDiff.empty, data)) + ) + } + case (Some(IfType.IfElse), 4) if checkData(bytes, data.length, 3, false) => { + runCondition(data(bytes(1))).flatMap(cond => + if(cond) executeOpcBlock(context, data(bytes(2)), data) + else executeOpcBlock(context, data(bytes(3)), data) + ) + } + } +} From fb1104b8dffb9053c3e7d3db7d228c965da7430f Mon Sep 17 00:00:00 2001 From: zl730 Date: Wed, 24 Jun 2020 17:56:21 +0800 Subject: [PATCH 010/391] fix test issues --- .../vsys/blockchain/contract/ContractGenHelper.scala | 4 ++-- .../vsys/blockchain/contract/DataTypeSpecification.scala | 3 ++- .../contract/channel/PaymentChannelContractGen.scala | 8 ++++---- .../contract/token/NonFungibleContractGen.scala | 6 +++--- .../blockchain/contract/token/SystemContractGen.scala | 6 +++--- .../vsys/blockchain/contract/token/TokenContractGen.scala | 6 +++--- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala b/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala index 33bd4e193..ab0c835cf 100644 --- a/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala +++ b/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala @@ -73,8 +73,8 @@ object ContractGenHelper extends TransactionGen { Bytes.concat(retType, paraType) } - def dataListGen(seqDataByte: Seq[Array[Byte]], seqDataType: Seq[DataType.Value]): Gen[Seq[DataEntry]] = - seqDataByte.zip(seqDataType).map { case (e1: Array[Byte], e2: DataType.Value) => DataEntry.create(e1, e2).explicitGet()} + def dataListGen(seqDataByte: Seq[Array[Byte]], seqDataType: Seq[DataType.DataTypeVal]): Gen[Seq[DataEntry]] = + seqDataByte.zip(seqDataType).map { case (e1: Array[Byte], e2: DataType.DataTypeVal) => DataEntry.create(e1, e2).explicitGet()} def basicContractTestGen(): Gen[(PrivateKeyAccount, Long, Long)] = for { master <- accountGen diff --git a/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala b/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala index 38d5f8424..e929e8bd2 100644 --- a/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala +++ b/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala @@ -18,7 +18,8 @@ class DataTypeSpecification extends PropSpec with PropertyChecks with GeneratorD DataType.fromByte(10) should be (Some(DataType.Boolean)) DataType.fromByte(11) should be (Some(DataType.ShortBytes)) DataType.fromByte(0) should be (None) - DataType.fromByte(12) should be (None) + DataType.fromByte(12) should be (Some(DataType.Balance)) + DataType.fromByte(13) should be (Some(DataType.OpcBlock)) } property("convert DataType to byte") { diff --git a/src/test/scala/vsys/blockchain/contract/channel/PaymentChannelContractGen.scala b/src/test/scala/vsys/blockchain/contract/channel/PaymentChannelContractGen.scala index e4e6dcbbe..637ebeaf5 100644 --- a/src/test/scala/vsys/blockchain/contract/channel/PaymentChannelContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/channel/PaymentChannelContractGen.scala @@ -39,7 +39,7 @@ trait PaymentChannelContractGen extends SystemContractGen description: String, fee: Long, ts: Long): Gen[RegisterContractTransaction] = RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() - def createChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def createChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = createIndex.toShort for { @@ -47,7 +47,7 @@ trait PaymentChannelContractGen extends SystemContractGen } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def updateExpiredTimeChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def updateExpiredTimeChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = updateExpiredTimeIndex.toShort for { @@ -55,7 +55,7 @@ trait PaymentChannelContractGen extends SystemContractGen } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def chargeChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def chargeChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = chargeIndex.toShort for { @@ -79,7 +79,7 @@ trait PaymentChannelContractGen extends SystemContractGen } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def executePaymentChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def executePaymentChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = executePaymentIndex.toShort for { diff --git a/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractGen.scala b/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractGen.scala index 66959e554..3d7cb7bab 100644 --- a/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractGen.scala @@ -60,7 +60,7 @@ trait NonFungibleContractGen { } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def transferNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def transferNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = transferIndex for { @@ -68,7 +68,7 @@ trait NonFungibleContractGen { } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def depositNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def depositNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = depositIndex for { @@ -76,7 +76,7 @@ trait NonFungibleContractGen { } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def withdrawNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def withdrawNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = withdrawIndex for { diff --git a/src/test/scala/vsys/blockchain/contract/token/SystemContractGen.scala b/src/test/scala/vsys/blockchain/contract/token/SystemContractGen.scala index 9f70d4bdf..40bf76c4c 100644 --- a/src/test/scala/vsys/blockchain/contract/token/SystemContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/SystemContractGen.scala @@ -27,21 +27,21 @@ trait SystemContractGen { } yield ExecuteContractFunctionTransaction.create(sender, ContractAccount.systemContractId, sysSend, data, attachment, fee, feeScale, ts).explicitGet() } - def transferVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def transferVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { for { data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) } yield ExecuteContractFunctionTransaction.create(signer, ContractAccount.systemContractId, sysTransfer, data, attachment, fee, feeScale, ts).explicitGet() } - def depositVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def depositVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { for { data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) } yield ExecuteContractFunctionTransaction.create(signer, ContractAccount.systemContractId, sysDeposit, data, attachment, fee, feeScale, ts).explicitGet() } - def withdrawVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def withdrawVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { for { data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractGen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractGen.scala index 178c7349e..fd728505a 100644 --- a/src/test/scala/vsys/blockchain/contract/token/TokenContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractGen.scala @@ -88,7 +88,7 @@ trait TokenContractGen { } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def transferTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def transferTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = if (split) transferIndex else (transferIndex - 1).toShort for { @@ -96,7 +96,7 @@ trait TokenContractGen { } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def depositTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def depositTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = if (split) depositIndex else (depositIndex - 1).toShort for { @@ -104,7 +104,7 @@ trait TokenContractGen { } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def withdrawTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def withdrawTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = if (split) withdrawIndex else (withdrawIndex - 1).toShort for { From dbf8fde3c06ccae99cc2c65810a1d6291c14b3dd Mon Sep 17 00:00:00 2001 From: zl730 Date: Sun, 28 Jun 2020 10:19:11 +0800 Subject: [PATCH 011/391] fix --- .../vsys/blockchain/contract/DataEntry.scala | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index 8cea787cb..0499e6581 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -80,13 +80,19 @@ object DataEntry { } private def parseArray(bytes: Array[Byte]): Either[ValidationError, (DataEntry, Array[Byte])] = { - DataType.fromByte(bytes(0)) match { - case Some(dt: DataType.DataTypeVal) if (dt.lenFixed && checkDataType(bytes.drop(1).take(dt.maxLen), dt)) => - Right((DataEntry(bytes.drop(1).take(dt.maxLen), dt), bytes.drop(1 + dt.maxLen))) - case Some(dt: DataType.DataTypeVal) if (dt.maxLen <= Short.MaxValue && checkDataType(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt)) => - Right((DataEntry(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt), bytes.drop(3 + Shorts.fromByteArray(bytes.drop(1).take(2))))) - case _ => Left(InvalidDataEntry) + bytes.headOption match { + case Some(b) => + DataType.fromByte(b) match { + case Some(dt: DataType.DataTypeVal) if (dt.lenFixed && checkDataType(bytes.drop(1).take(dt.maxLen), dt)) => + Right((DataEntry(bytes.drop(1).take(dt.maxLen), dt), bytes.drop(1 + dt.maxLen))) + case Some(dt: DataType.DataTypeVal) if (!dt.lenFixed && dt.maxLen <= Short.MaxValue && checkDataType(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt)) => + Right((DataEntry(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt), bytes.drop(3 + Shorts.fromByteArray(bytes.drop(1).take(2))))) + case _ => Left(InvalidDataEntry) + } + case _ => + Left(InvalidDataEntry) } + } def serializeArrays(ds: Seq[DataEntry]): Array[Byte] = { @@ -97,7 +103,7 @@ object DataEntry { val length = Shorts.fromByteArray(bytes.take(2)) (0 until length).foldLeft(Right((Seq.empty[DataEntry], bytes.drop(2))): Either[ValidationError, (Seq[DataEntry], Array[Byte])]) { case (accPos, _) => accPos.flatMap(ap => parseArray(ap._2) match { - case Right((arr, nextPos)) => Right((ap._1 :+ arr, nextPos)) + case Right((arr, suffix)) => Right((ap._1 :+ arr, suffix)) case Left(l) => Left(l) }) } match { From 345842593495d6e586c9d513b9577617bba69927 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 21 Jul 2020 09:48:44 +0800 Subject: [PATCH 012/391] update version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 417da3303..3a4397c6f 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ enablePlugins(sbtdocker.DockerPlugin, JavaServerAppPackaging, JDebPackaging, Sys name := "vsys" organization := "systems.v" -version := "0.3.1" +version := "0.3.2" scalaVersion in ThisBuild := "2.12.6" crossPaths := false publishArtifact in (Compile, packageDoc) := false From 3508bc682b2d3b2c5b0913969fd08059f4b3b756 Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 28 Jul 2020 16:04:17 +0800 Subject: [PATCH 013/391] modify AssertOpcDiff --- .../state/opcdiffs/AssertOpcDiff.scala | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiff.scala index 9c20b55d1..9b95ca7a6 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiff.scala @@ -18,43 +18,51 @@ object AssertOpcDiff extends OpcDiffer { else if (v.data sameElements Array(1.toByte)) Right(OpcDiff.empty) else - Left(GenericError(s"Invalid Assert (Boolean True): Value False")) + Left(GenericError(s"Invalid Assert (Boolean True): Value ${v.json} is False")) } def gtEq0(v: DataEntry): Either[ValidationError, OpcDiff] = { - if (v.dataType == DataType.Amount && Longs.fromByteArray(v.data) >= 0) + if (v.dataType != DataType.Amount) + Left(ContractDataTypeMismatch) + else if (Longs.fromByteArray(v.data) >= 0) Right(OpcDiff.empty) else - Left(GenericError(s"Invalid Assert (gteq0): Value ${Longs.fromByteArray(v.data)} is negative")) + Left(GenericError(s"Invalid Assert (gteq0): Value ${v.json} is negative")) } def ltEq(v1: DataEntry, v2: DataEntry): Either[ValidationError, OpcDiff] = { - if (v1.dataType == DataType.Amount && v2.dataType == DataType.Amount - && Longs.fromByteArray(v1.data) <= Longs.fromByteArray(v2.data)) + if (v1.dataType != DataType.Amount || v2.dataType != DataType.Amount) + Left(ContractDataTypeMismatch) + else if (Longs.fromByteArray(v1.data) <= Longs.fromByteArray(v2.data)) Right(OpcDiff.empty) else - Left(GenericError(s"Invalid Assert (lteq0): Value ${Longs.fromByteArray(v2.data)} is larger than $v1")) + Left(GenericError(s"Invalid Assert (lteq0): Value ${v1.json} " + + s"is larger than ${v2.json}")) } def ltInt64(m: DataEntry): Either[ValidationError, OpcDiff] = { - if (m.dataType == DataType.Amount && Longs.fromByteArray(m.data) <= Long.MaxValue) + if (m.dataType != DataType.Amount) + Left(ContractDataTypeMismatch) + else if (Longs.fromByteArray(m.data) <= Long.MaxValue) Right(OpcDiff.empty) else - Left(GenericError(s"Invalid Assert (ltint64): Value ${Longs.fromByteArray(m.data)} is invalid")) + Left(GenericError(s"Invalid Assert (ltint64): Value ${m.json} is invalid")) } def gt0(v: DataEntry): Either[ValidationError, OpcDiff] = { - if (v.dataType == DataType.Amount && Longs.fromByteArray(v.data) > 0) + if (v.dataType != DataType.Amount) + Left(ContractDataTypeMismatch) + else if (Longs.fromByteArray(v.data) > 0) Right(OpcDiff.empty) else - Left(GenericError(s"Invalid Assert (gt0): Value $v is non-positive")) + Left(GenericError(s"Invalid Assert (gt0): Value ${v.json} is non-positive")) } def equal(add1: DataEntry, add2: DataEntry): Either[ValidationError, OpcDiff] = { if (add1.bytes sameElements add2.bytes) Right(OpcDiff.empty) else - Left(GenericError(s"Invalid Assert (eq): DataEntry ${add1.data} is not equal to ${add2.data}")) + Left(GenericError(s"Invalid Assert (eq): DataEntry ${add1.json} is not equal to ${add2.json}")) } def isCallerOrigin(context: ExecutionContext)(address: DataEntry): Either[ValidationError, OpcDiff] = { From 8521b10602f40aee41999fbcfb03f506e9e93a4b Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 28 Jul 2020 16:07:56 +0800 Subject: [PATCH 014/391] add AssertOpcDiffTest --- .../state/opcdiffs/AssertOpcDiffTest.scala | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala new file mode 100644 index 000000000..9c529f126 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala @@ -0,0 +1,94 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Ints, Longs} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidCaller, + ContractInvalidSigner, GenericError} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.{Left, Right} + +class AssertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + val state = newState() + + property("test assert opcs") { + AssertOpcDiff.assertTrue(DataEntry(Array(1.toByte), DataType.Boolean)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.assertTrue(DataEntry(Array(0.toByte), DataType.Boolean)) should be ( + Left(GenericError(s"Invalid Assert (Boolean True): " + + s"Value ${DataEntry(Array(0.toByte), DataType.Boolean).json} is False"))) + AssertOpcDiff.assertTrue(DataEntry(Array(1.toByte), DataType.ShortBytes)) should be (Left(ContractDataTypeMismatch)) + + AssertOpcDiff.gtEq0(DataEntry(Longs.toByteArray(1), DataType.Amount)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.gtEq0(DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.gtEq0(DataEntry(Longs.toByteArray(-1), DataType.Amount)) should be ( + Left(GenericError(s"Invalid Assert (gteq0): " + + s"Value ${DataEntry(Longs.toByteArray(-1), DataType.Amount).json} is negative"))) + + AssertOpcDiff.ltEq(DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.ltEq(DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.ShortBytes)) should be (Left(ContractDataTypeMismatch)) + AssertOpcDiff.ltEq(DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(0), DataType.Amount)) should be ( + Left(GenericError(s"Invalid Assert (lteq0): " + + s"Value ${DataEntry(Longs.toByteArray(1), DataType.Amount).json} " + + s"is larger than ${DataEntry(Longs.toByteArray(0), DataType.Amount).json}"))) + + AssertOpcDiff.ltInt64(DataEntry(Longs.toByteArray(1), DataType.Amount)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.ltInt64(DataEntry(Longs.toByteArray(0), DataType.ShortBytes)) should be ( + Left(ContractDataTypeMismatch)) + + AssertOpcDiff.gt0(DataEntry(Longs.toByteArray(1), DataType.Amount)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.gt0(DataEntry(Longs.toByteArray(0), DataType.Amount)) should be ( + Left(GenericError(s"Invalid Assert (gt0): " + + s"Value ${DataEntry(Longs.toByteArray(0), DataType.Amount).json} is non-positive"))) + AssertOpcDiff.gt0(DataEntry(Longs.toByteArray(-1), DataType.Amount)) should be ( + Left(GenericError(s"Invalid Assert (gt0): " + + s"Value ${DataEntry(Longs.toByteArray(-1), DataType.Amount).json} is non-positive"))) + + AssertOpcDiff.equal(DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.equal(DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Ints.toByteArray(1), DataType.Int32)) should be ( + Left(GenericError(s"Invalid Assert (eq): DataEntry " + + s"${DataEntry(Longs.toByteArray(1), DataType.Amount).json} " + + s"is not equal to ${DataEntry(Ints.toByteArray(1), DataType.Int32).json}"))) + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + AssertOpcDiff.isCallerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, + DataType.Address)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.isCallerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, + DataType.ContractAccount)) should be (Left(ContractDataTypeMismatch)) + AssertOpcDiff.isCallerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, + DataType.Address)) should be (Left(ContractInvalidCaller)) + + AssertOpcDiff.isSignerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, + DataType.Address)) should be (Right(OpcDiff.empty)) + AssertOpcDiff.isSignerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, + DataType.ContractAccount)) should be (Left(ContractDataTypeMismatch)) + AssertOpcDiff.isSignerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, + DataType.Address)) should be (Left(ContractInvalidSigner)) + } +} From 91f7f04f5bd90e4c9e7b0ee53e1d405d645d570e Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 28 Jul 2020 21:30:56 +0800 Subject: [PATCH 015/391] delete unused context --- .../state/opcdiffs/BasicOpcDiff.scala | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 72d5f16a6..498e3a184 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -9,8 +9,8 @@ import scala.util.{Left, Right, Try} object BasicOpcDiff extends OpcDiffer { - def add(context: ExecutionContext)(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def add(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (x.dataType == y.dataType) { val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) supportList.find(a => a == x.dataType) match { @@ -40,8 +40,8 @@ object BasicOpcDiff extends OpcDiffer { } else Left(ContractDataTypeMismatch) } - def minus(context: ExecutionContext)(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def minus(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (x.dataType == y.dataType) { val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) supportList.find(a => a == x.dataType) match { @@ -71,8 +71,8 @@ object BasicOpcDiff extends OpcDiffer { } else Left(ContractDataTypeMismatch) } - def multiply(context: ExecutionContext)(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def multiply(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (x.dataType == y.dataType) { val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) supportList.find(a => a == x.dataType) match { @@ -102,8 +102,8 @@ object BasicOpcDiff extends OpcDiffer { } else Left(ContractDataTypeMismatch) } - def divide(context: ExecutionContext)(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def divide(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (x.dataType == y.dataType) { val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) supportList.find(a => a == x.dataType) match { @@ -133,7 +133,7 @@ object BasicOpcDiff extends OpcDiffer { } else Left(ContractDataTypeMismatch) } - def minimum(context: ExecutionContext)(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + def minimum(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (x.dataType == y.dataType) { val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) @@ -149,8 +149,8 @@ object BasicOpcDiff extends OpcDiffer { } else Left(ContractDataTypeMismatch) } - def maximum(context: ExecutionContext)(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def maximum(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (x.dataType == y.dataType) { val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) supportList.find(a => a == x.dataType) match { @@ -165,15 +165,15 @@ object BasicOpcDiff extends OpcDiffer { } else Left(ContractDataTypeMismatch) } - def concat(context: ExecutionContext)(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def concat(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { for { res <- DataEntry.create(x.data ++ y.data, DataType.ShortBytes) } yield dataStack.patch(pointer, Seq(res), 1) } - def constantGet(context: ExecutionContext)(constant: Array[Byte], dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def constantGet(constant: Array[Byte], dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { DataEntry.fromBytes(constant) match { case Right(v) => Right(dataStack.patch(pointer, Seq(v), 1)) case Left(e) => Left(e) @@ -184,22 +184,22 @@ object BasicOpcDiff extends OpcDiffer { sealed case class basicTypeVal( basicType: Int, len: Int, - differ: (ExecutionContext, Array[Byte], Seq[DataEntry]) => Either[ValidationError, Seq[DataEntry]]) + differ: (Array[Byte], Seq[DataEntry]) => Either[ValidationError, Seq[DataEntry]]) extends Val(basicType) { def *(n: Int): Int = n * basicType } - val Add = basicTypeVal(1, 4, (c, b, d) => add(c)(d(b(1)), d(b(2)), d, b(3))) - val Minus = basicTypeVal(2, 4, (c, b, d) => minus(c)(d(b(1)), d(b(2)), d, b(3))) - val Multiply = basicTypeVal(3, 4, (c, b, d) => multiply(c)(d(b(1)), d(b(2)), d, b(3))) - val Divide = basicTypeVal(4, 4, (c, b, d) => divide(c)(d(b(1)), d(b(2)), d, b(3))) - val Minimum = basicTypeVal(5, 4, (c, b, d) => minimum(c)(d(b(1)), d(b(2)), d, b(3))) - val Maximum = basicTypeVal(6, 4, (c, b, d) => maximum(c)(d(b(1)), d(b(2)), d, b(3))) - val Concat = basicTypeVal(7, 4, (c, b, d) => concat(c)(d(b(1)), d(b(2)), d, b(3))) - val ConstantGet = basicTypeVal(8, 2, (c, b, d) => constantGet(c)(b.slice(1, b.length-1), d, b(b.length-1))) + val Add = basicTypeVal(1, 4, (b, d) => add(d(b(1)), d(b(2)), d, b(3))) + val Minus = basicTypeVal(2, 4, (b, d) => minus(d(b(1)), d(b(2)), d, b(3))) + val Multiply = basicTypeVal(3, 4, (b, d) => multiply(d(b(1)), d(b(2)), d, b(3))) + val Divide = basicTypeVal(4, 4, (b, d) => divide(d(b(1)), d(b(2)), d, b(3))) + val Minimum = basicTypeVal(5, 4, (b, d) => minimum(d(b(1)), d(b(2)), d, b(3))) + val Maximum = basicTypeVal(6, 4, (b, d) => maximum(d(b(1)), d(b(2)), d, b(3))) + val Concat = basicTypeVal(7, 4, (b, d) => concat(d(b(1)), d(b(2)), d, b(3))) + val ConstantGet = basicTypeVal(8, 2, (b, d) => constantGet(b.slice(1, b.length-1), d, b(b.length-1))) } override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(BasicType(f)).toOption) match { - case Some(t: BasicType.basicTypeVal) if checkBytesLength(bytes, t) => t.differ(context, bytes, data) + case Some(t: BasicType.basicTypeVal) if checkBytesLength(bytes, t) => t.differ(bytes, data) case _ => Left(ContractInvalidOPCData) } From f38295a3cf6941f2c0ae69aef91c2f8cbea08d5e Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 28 Jul 2020 21:33:17 +0800 Subject: [PATCH 016/391] add BasicOpcDiffTest --- .../state/opcdiffs/BasicOpcDiffTest.scala | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala new file mode 100644 index 000000000..c324bb244 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -0,0 +1,127 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Ints, Longs} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.contract.{DataEntry, DataType} +import vsys.blockchain.contract.DataEntry.maxShortBytesLength +import vsys.blockchain.transaction.{TransactionGen, ValidationError} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractUnsupportedOPC, InvalidDataEntry} + +import scala.util.{Left, Right} + +class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + property("test basic opcs") { + BasicOpcDiff.add( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(2), DataType.Amount)))) + BasicOpcDiff.add( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.add( + DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 0) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.add( + DataEntry(Longs.toByteArray(1), DataType.ShortText), + DataEntry(Longs.toByteArray(1), DataType.ShortText), + Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + + BasicOpcDiff.minus( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) + BasicOpcDiff.minus( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.minus( + DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), + DataEntry(Longs.toByteArray(-1), DataType.Amount), + Seq.empty, 0) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.minus( + DataEntry(Longs.toByteArray(1), DataType.ShortText), + DataEntry(Longs.toByteArray(1), DataType.ShortText), + Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + + BasicOpcDiff.multiply( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.multiply( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.multiply( + DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), + DataEntry(Longs.toByteArray(2), DataType.Amount), + Seq.empty, 0) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.multiply( + DataEntry(Longs.toByteArray(1), DataType.ShortText), + DataEntry(Longs.toByteArray(1), DataType.ShortText), + Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + + BasicOpcDiff.divide( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.divide( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.divide( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(0), DataType.Amount), + Seq.empty, 0) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.divide( + DataEntry(Longs.toByteArray(1), DataType.ShortText), + DataEntry(Longs.toByteArray(1), DataType.ShortText), + Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + + BasicOpcDiff.minimum( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(0), DataType.Amount), + Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) + BasicOpcDiff.minimum( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.minimum( + DataEntry(Longs.toByteArray(1), DataType.ShortText), + DataEntry(Longs.toByteArray(1), DataType.ShortText), + Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + + BasicOpcDiff.maximum( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(0), DataType.Amount), + Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.maximum( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.maximum( + DataEntry(Longs.toByteArray(1), DataType.ShortText), + DataEntry(Longs.toByteArray(1), DataType.ShortText), + Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + + BasicOpcDiff.concat( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 0) should be ( + Right(Seq(DataEntry.create(Longs.toByteArray(1) ++ Longs.toByteArray(1), + DataType.ShortBytes).right.get))) + BasicOpcDiff.concat( + DataEntry(Array.fill(maxShortBytesLength){0}, DataType.ShortBytes), + DataEntry(Array.fill(1){0}, DataType.ShortBytes), + Seq.empty, 0) should be (Left(InvalidDataEntry)) + + BasicOpcDiff.constantGet(Array(DataType.Amount.id.toByte) ++ Longs.toByteArray(1), + Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.constantGet(Array(DataType.Amount.id.toByte) ++ Ints.toByteArray(1), + Seq.empty, 0) should be (Left(InvalidDataEntry)) + } +} + From f3f06c6e9b6b79912fe5108c799da413978b01d3 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 30 Jul 2020 17:06:51 +0800 Subject: [PATCH 017/391] ignore metals --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 5a7487430..88b53f3c4 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,9 @@ test/*/data/* src/test/**/.DS_Store *.sublime-* + +# metals +.metals/ +.bloop/ +.ammonite/ +project/metals.sbt From 872ef9089963dbdab45e5881cea0d192288e1259 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 30 Jul 2020 17:14:29 +0800 Subject: [PATCH 018/391] fix bug --- .../blockchain/state/opcdiffs/CDBVOpcDiff.scala | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiff.scala index 94e62857c..9c32c4f00 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiff.scala @@ -39,15 +39,14 @@ object CDBVOpcDiff extends OpcDiffer { def mapValueAdd(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataValue: DataEntry): Either[ValidationError, OpcDiff] = { val combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes) - if (!checkStateMap(stateMap, keyValue.dataType, dataValue.dataType)) + if (!checkStateMap(stateMap, keyValue.dataType, dataValue.dataType)) { Left(ContractInvalidStateMap) - if (dataValue.dataType == DataType.Amount){ + } else if (dataValue.dataType == DataType.Amount) { val cntBalance = context.state.contractNumInfo(combinedKey) val addAmount = Longs.fromByteArray(dataValue.data) if (addAmount < 0){ Left(InvalidDataEntry) - } - if (Try(Math.addExact(cntBalance, addAmount)).isFailure) + } else if (Try(Math.addExact(cntBalance, addAmount)).isFailure) Left(ValidationError.OverflowError) else Right(OpcDiff(contractNumDB = Map(combinedKey -> addAmount))) @@ -58,15 +57,14 @@ object CDBVOpcDiff extends OpcDiffer { def mapValueMinus(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataValue: DataEntry): Either[ValidationError, OpcDiff] = { val combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes) - if (!checkStateMap(stateMap, keyValue.dataType, dataValue.dataType)) + if (!checkStateMap(stateMap, keyValue.dataType, dataValue.dataType)) { Left(ContractInvalidStateMap) - if (dataValue.dataType == DataType.Amount){ + } else if (dataValue.dataType == DataType.Amount) { val cntBalance = context.state.contractNumInfo(combinedKey) val minusAmount = Longs.fromByteArray(dataValue.data) if (minusAmount < 0){ Left(InvalidDataEntry) - } - if (cntBalance >= minusAmount) + } else if (cntBalance >= minusAmount) Right(OpcDiff(contractNumDB = Map(combinedKey -> -minusAmount))) else Left(ContractMapValueInsufficient) } From b8104b9b15966ca12b02bfd2b6ad0b37af9e19d2 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 30 Jul 2020 17:15:01 +0800 Subject: [PATCH 019/391] add CDBVOpcDiffTest --- .../state/opcdiffs/CDBVOpcDiffTest.scala | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala new file mode 100644 index 000000000..b823052cf --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala @@ -0,0 +1,104 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.Longs +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidStateMap, + ContractInvalidStateVariable, ContractMapValueInsufficient, InvalidDataEntry} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.Left + +class CDBVOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + property("test CDBV opcs") { + ByteStr(CDBVOpcDiff.set(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount)).right.get.contractDB( + ByteStr(tx.right.get.contractId.bytes.arr ++ Array[Byte](0.toByte)))) shouldEqual ByteStr(DataEntry( + Longs.toByteArray(0), DataType.Amount).bytes) + CDBVOpcDiff.set(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 2.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidStateVariable)) + + ByteStr(CDBVOpcDiff.mapSet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount), + DataEntry(Longs.toByteArray(0), DataType.Amount)).right.get.contractDB( + ByteStr(tx.right.get.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( + Longs.toByteArray(0), DataType.Amount).bytes))) shouldEqual ByteStr(DataEntry( + Longs.toByteArray(0), DataType.Amount).bytes) + CDBVOpcDiff.mapSet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 2.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidStateMap)) + + CDBVOpcDiff.mapValueAdd(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(0), DataType.Amount)).right.get.contractNumDB( + ByteStr(tx.right.get.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( + Longs.toByteArray(0), DataType.Amount).bytes)) shouldEqual 0 + CDBVOpcDiff.mapValueAdd(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 2.toByte, 2.toByte), DataEntry( + Longs.toByteArray(0), DataType.ShortBytes), DataEntry( + Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidStateMap)) + CDBVOpcDiff.mapValueAdd(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(-1), DataType.Amount)) should be (Left(InvalidDataEntry)) + CDBVOpcDiff.mapValueAdd(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 4.toByte), DataEntry( + Longs.toByteArray(1), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) + + CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(0), DataType.Amount)).right.get.contractNumDB( + ByteStr(tx.right.get.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( + Longs.toByteArray(0), DataType.Amount).bytes)) shouldEqual 0 + CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 2.toByte, 2.toByte), DataEntry( + Longs.toByteArray(0), DataType.ShortBytes), DataEntry( + Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidStateMap)) + CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(-1), DataType.Amount)) should be (Left(InvalidDataEntry)) + CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(1), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Amount)) should be (Left(ContractMapValueInsufficient)) + CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 4.toByte), DataEntry( + Longs.toByteArray(1), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) + } +} + From 2664c25873625413d110751e15fa892ab7b77847 Mon Sep 17 00:00:00 2001 From: Icermli Date: Fri, 31 Jul 2020 15:12:24 +0800 Subject: [PATCH 020/391] add overloaded checkState func and fix bug --- src/main/scala/vsys/blockchain/contract/Contract.scala | 6 ++++++ .../scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index 61d81eb19..d25ba0d45 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -132,9 +132,15 @@ object Contract extends ScorexLogging { } } + def checkStateVar(stateVar: Array[Byte]): Boolean = + stateVar.length == 2 + def checkStateVar(stateVar: Array[Byte], dataType: DataType.Value): Boolean = stateVar.length == 2 && dataType == DataType(stateVar(1)) + def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.Value): Boolean = + stateMap.length == 3 && keyDataType == DataType(stateMap(1)) + def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.Value, valueDataType: DataType.Value): Boolean = stateMap.length == 3 && keyDataType == DataType(stateMap(1)) && valueDataType == DataType(stateMap(2)) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala index 3d92b1627..408772793 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala @@ -13,7 +13,7 @@ object CDBVROpcDiff extends OpcDiffer { def get(context: ExecutionContext)(stateVar: Array[Byte], dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateVar(stateVar, DataType(stateVar(1)))) { + if (!checkStateVar(stateVar)) { Left(ContractInvalidStateVariable) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) @@ -27,7 +27,7 @@ object CDBVROpcDiff extends OpcDiffer { def mapGet(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)))) { + if (!checkStateMap(stateMap, keyValue.dataType)) { Left(ContractInvalidStateMap) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) @@ -42,7 +42,7 @@ object CDBVROpcDiff extends OpcDiffer { def mapGetOrDefault(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)))) { + if (!checkStateMap(stateMap, keyValue.dataType)) { Left(ContractInvalidStateMap) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) From d701ae5458bd071f1371804b7e0620ad72b465ec Mon Sep 17 00:00:00 2001 From: Icermli Date: Fri, 31 Jul 2020 15:13:29 +0800 Subject: [PATCH 021/391] add CDBVROpcDiffTest --- .../state/opcdiffs/BasicOpcDiffTest.scala | 1 - .../state/opcdiffs/CDBVOpcDiffTest.scala | 1 - .../state/opcdiffs/CDBVROpcDiffTest.scala | 75 +++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala index c324bb244..2d0315c52 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -124,4 +124,3 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven Seq.empty, 0) should be (Left(InvalidDataEntry)) } } - diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala index b823052cf..0c33c3865 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala @@ -101,4 +101,3 @@ class CDBVOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenP Longs.toByteArray(1), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) } } - diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala new file mode 100644 index 000000000..4d288fce4 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala @@ -0,0 +1,75 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.Longs +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.{ContractInvalidStateMap, ContractLocalVariableIndexOutOfRange, + ContractStateMapNotDefined, ContractStateVariableNotDefined} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.Left + +class CDBVROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + property("test CDBVR opcs") { + CDBVROpcDiff.get(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte), Seq.empty, 0) should be (Left(ContractStateVariableNotDefined)) + CDBVROpcDiff.get(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte), Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + + CDBVROpcDiff.mapGet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be ( + Left(ContractStateMapNotDefined)) + CDBVROpcDiff.mapGet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractInvalidStateMap)) + CDBVROpcDiff.mapGet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(1), DataType.Amount), Seq.empty, 1) should be ( + Left(ContractLocalVariableIndexOutOfRange)) + + CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be ( + Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) + CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 9.toByte, 9.toByte), DataEntry( + Longs.toByteArray(1), DataType.Timestamp), Seq.empty, 0) should be ( + Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Timestamp)))) + CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractInvalidStateMap)) + CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 4.toByte, 4.toByte), DataEntry( + Longs.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractStateMapNotDefined)) + CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( + Longs.toByteArray(1), DataType.Amount), Seq.empty, 1) should be ( + Left(ContractLocalVariableIndexOutOfRange)) + } +} From 5ae7d3f67be61c44ebf88d8462d0a3467f3a1a66 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 3 Aug 2020 12:27:31 +0800 Subject: [PATCH 022/391] modify compareOpcDiff --- .../vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala index fa1d10f45..fb137cb6d 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala @@ -9,8 +9,8 @@ import scala.util.{Left, Right, Try} object CompareOpcDiff extends OpcDiffer { - def geq(context: ExecutionContext)(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def geq(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (x.dataType == y.dataType) { val supportList = List(DataType.Amount, DataType.Timestamp) supportList.find(a => a == x.dataType) match { @@ -34,7 +34,7 @@ object CompareOpcDiff extends OpcDiffer { override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(CompareType(f)).toOption) match { - case Some(CompareType.Geq) if bytes.length == 4 => geq(context)(data(bytes(1)), data(bytes(2)), data, bytes(3)) + case Some(CompareType.Geq) if bytes.length == 4 => geq(data(bytes(1)), data(bytes(2)), data, bytes(3)) case _ => Left(ContractInvalidOPCData) } } From 968a47953e130fed9baefa1e4f541ebaa058f926 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 3 Aug 2020 12:28:10 +0800 Subject: [PATCH 023/391] add CompareOpcDiffTest --- .../state/opcdiffs/CDBVROpcDiffTest.scala | 11 ++++---- .../state/opcdiffs/CompareOpcDiffTest.scala | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala index 4d288fce4..6f7fe5374 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala @@ -1,14 +1,13 @@ package vsys.blockchain.state.opcdiffs -import com.google.common.primitives.Longs +import com.google.common.primitives.{Ints, Longs} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.{TransactionGen, TransactionParser} -import vsys.blockchain.transaction.ValidationError.{ContractInvalidStateMap, ContractLocalVariableIndexOutOfRange, - ContractStateMapNotDefined, ContractStateVariableNotDefined} +import vsys.blockchain.transaction.ValidationError.{ContractInvalidStateMap, ContractLocalVariableIndexOutOfRange, ContractStateMapNotDefined, ContractStateVariableNotDefined} import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings @@ -38,7 +37,7 @@ class CDBVROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven CDBVROpcDiff.mapGet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx.right.get).right.get)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( - Longs.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidStateMap)) CDBVROpcDiff.mapGet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx.right.get).right.get)( @@ -59,12 +58,12 @@ class CDBVROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx.right.get).right.get)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( - Longs.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidStateMap)) CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx.right.get).right.get)( Array[Byte](0.toByte, 4.toByte, 4.toByte), DataEntry( - Longs.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( Left(ContractStateMapNotDefined)) CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx.right.get).right.get)( diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala new file mode 100644 index 000000000..02bbe3ead --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala @@ -0,0 +1,28 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Ints, Longs} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.contract.{DataEntry, DataType} +import vsys.blockchain.transaction.TransactionGen +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractUnsupportedOPC} + +import scala.util.{Left, Right} + +class CompareOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + property("test compare opcs") { + CompareOpcDiff.geq(DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be ( + Right(Seq(DataEntry(Array(1.toByte), DataType.Boolean)))) + CompareOpcDiff.geq(DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be ( + Right(Seq(DataEntry(Array(0.toByte), DataType.Boolean)))) + CompareOpcDiff.geq(DataEntry(Ints.toByteArray(0), DataType.Int32), DataEntry( + Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractUnsupportedOPC)) + CompareOpcDiff.geq(DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractDataTypeMismatch)) + } +} From 24c1bec87b06b832c3cbbd0228bd48fe342ae215 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 3 Aug 2020 14:06:51 +0800 Subject: [PATCH 024/391] fix bug --- src/main/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiff.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiff.scala index 74d9ebd2e..7c83a8257 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiff.scala @@ -60,7 +60,7 @@ object LoadOpcDiff extends OpcDiffer { if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) } else { - Right(dataStack.patch(pointer, Seq(DataEntry(Longs.toByteArray(context.height), DataType.Int32)), 1)) + Right(dataStack.patch(pointer, Seq(DataEntry(Ints.toByteArray(context.height), DataType.Int32)), 1)) } } From c4115c4de2a8c78acf5d7a20981b7564a5ed958d Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 3 Aug 2020 14:09:34 +0800 Subject: [PATCH 025/391] add LoadOpcDiffTest --- .../state/opcdiffs/LoadOpcDiffTest.scala | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala new file mode 100644 index 000000000..a4d49217a --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala @@ -0,0 +1,82 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Ints, Longs, Shorts} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.ContractLocalVariableIndexOutOfRange +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.{Left, Right} + +class LoadOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + property("test load opcs") { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + LoadOpcDiff.signer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 0) should be (Right(Seq(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address)))) + LoadOpcDiff.signer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + + LoadOpcDiff.caller(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 0) should be (Right(Seq(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address)))) + LoadOpcDiff.caller(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + + LoadOpcDiff.timestamp(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 0) should be (Right(Seq(DataEntry( + Longs.toByteArray(0), DataType.Timestamp)))) + LoadOpcDiff.timestamp(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + + LoadOpcDiff.lastTokenIndex(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 0) should be (Right(Seq(DataEntry( + Ints.toByteArray(-1), DataType.Int32)))) + LoadOpcDiff.lastTokenIndex(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + + LoadOpcDiff.transactionId(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 0) should be (Right(Seq(DataEntry( + Shorts.toByteArray(tx.right.get.id.arr.length.toShort) ++ tx.right.get.id.arr, DataType.ShortBytes)))) + LoadOpcDiff.transactionId(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + + LoadOpcDiff.signerPublicKey(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 0) should be (Right(Seq(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).publicKey, DataType.PublicKey)))) + LoadOpcDiff.signerPublicKey(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + + LoadOpcDiff.height(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 0) should be (Right(Seq(DataEntry( + Ints.toByteArray(1), DataType.Int32)))) + LoadOpcDiff.height(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + } +} From aeb66d1d53915191a08fbb1e0664cf342106f077 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 3 Aug 2020 14:41:53 +0800 Subject: [PATCH 026/391] add ReturnOpcDiffTest --- .../state/opcdiffs/ReturnOpcDiffTest.scala | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala new file mode 100644 index 000000000..d779de1b0 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala @@ -0,0 +1,30 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.Longs +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.ContractUnsupportedOPC +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.Left + +class ReturnOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + property("test return opcs") { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + ReturnOpcDiff.value(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(Seq.empty, 0) should be ( + Left(ContractUnsupportedOPC)) + } +} From 5fd98ed801ffd66a2fa0bca2243cdc0af34dad7c Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 4 Aug 2020 17:16:35 +0800 Subject: [PATCH 027/391] add TDBAOpcDiffTest --- .../state/opcdiffs/TDBAOpcDiffTest.scala | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala new file mode 100644 index 000000000..c2def3a26 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala @@ -0,0 +1,120 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Ints, Longs} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.{ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, GenericError, InvalidContractAddress} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.{Left, Right} + +class TDBAOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + property("test TDBA opcs") { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + TDBAOpcDiff.deposit(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)) should be ( + Left(ContractInvalidTokenIndex)) + TDBAOpcDiff.deposit(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( + Left(ContractDataTypeMismatch)) + + TDBAOpcDiff.withdraw(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)) should be ( + Left(ContractInvalidTokenIndex)) + TDBAOpcDiff.withdraw(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( + Left(ContractDataTypeMismatch)) + + TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( + Right(OpcDiff.empty)) + TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( + Left(InvalidContractAddress)) + TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( + Right(OpcDiff.empty)) + TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( + Left(InvalidContractAddress)) + TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 3) should be ( + Left(GenericError("Invalid Call Index"))) + TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Function, 1) should be ( + Left(GenericError("Invalid Call Type"))) + + TDBAOpcDiff.contractTransfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) + TDBAOpcDiff.contractTransfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidTokenIndex)) + + TDBAOpcDiff.basicTransfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) + TDBAOpcDiff.basicTransfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)( + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidTokenIndex)) + + TDBAOpcDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) + } +} From ebfde065fb1dccf2704c456062a6e9001d7ff21c Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 4 Aug 2020 17:29:44 +0800 Subject: [PATCH 028/391] add TDBAROpcDiffTest --- .../state/opcdiffs/TDBAOpcDiffTest.scala | 3 +- .../state/opcdiffs/TDBAROpcDiffTest.scala | 46 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala index c2def3a26..b119fde8b 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala @@ -8,7 +8,8 @@ import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataTyp import vsys.blockchain.state.ByteStr import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.{TransactionGen, TransactionParser} -import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, GenericError, InvalidContractAddress} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, + GenericError, InvalidContractAddress} import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala new file mode 100644 index 000000000..140bab375 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala @@ -0,0 +1,46 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Ints, Longs} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.{ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, + GenericError, InvalidContractAddress} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.{Left, Right} + +class TDBAROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + property("test TDBAR opcs") { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + TDBAROpcDiff.balance(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractInvalidTokenIndex)) + TDBAROpcDiff.balance(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( + Left(ContractDataTypeMismatch)) + + TDBAROpcDiff.balanceWithoutTokenIndex( + ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + Seq.empty, 0) should be ( + Left(ContractInvalidTokenIndex)) + } +} From 5b27433f204d8e08d218d19a469cd46103afa38e Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 4 Aug 2020 17:31:50 +0800 Subject: [PATCH 029/391] fix import --- .../blockchain/state/opcdiffs/TDBAROpcDiffTest.scala | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala index 140bab375..36b86089a 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala @@ -3,17 +3,15 @@ package vsys.blockchain.state.opcdiffs import com.google.common.primitives.{Ints, Longs} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} -import vsys.account.{ContractAccount, PrivateKeyAccount} -import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataType, ExecutionContext} -import vsys.blockchain.state.ByteStr +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.{TransactionGen, TransactionParser} -import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, - GenericError, InvalidContractAddress} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex} import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings -import scala.util.{Left, Right} +import scala.util.Left class TDBAROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { From 11d143110f4d94074a0785b010a9220791917846 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 5 Aug 2020 09:45:58 +0800 Subject: [PATCH 030/391] TDBOpcDiffTest --- .../state/opcdiffs/TDBOpcDiffTest.scala | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala new file mode 100644 index 000000000..4f36f667e --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala @@ -0,0 +1,64 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Bytes, Ints, Longs} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, + ContractInvalidTokenInfo} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.Left + +class TDBOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + property("test TDB opcs") { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + val context = ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get + + val tokenID: ByteStr = tokenIdFromBytes(context.contractId.bytes.arr, Ints.toByteArray(0)).right.get + + TDBOpcDiff.newToken(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Array.fill(13){1}, DataType.ShortText)) should be (Left(ContractDataTypeMismatch)) + TDBOpcDiff.newToken(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Array.fill(13){1}, DataType.ShortText)) should be (Left(ContractInvalidTokenInfo)) + TDBOpcDiff.newToken(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(-1), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Amount), DataEntry( + Array.fill(13){1}, DataType.ShortText)) should be (Left(ContractInvalidTokenInfo)) + TDBOpcDiff.newToken(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Amount), DataEntry( + Array.fill(13){1}, DataType.ShortText)).right.get.tokenDB( + ByteStr(Bytes.concat(tokenID.arr, Array(0.toByte)))) shouldEqual DataEntry( + Longs.toByteArray(0), DataType.Amount).bytes + + TDBOpcDiff.split(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidTokenIndex)) + TDBOpcDiff.split(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) + } +} From 933a87e7f0eccf6cc84c17acd62b10f7febb65e3 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 5 Aug 2020 11:06:21 +0800 Subject: [PATCH 031/391] add TDBROpcDiffTest --- .../state/opcdiffs/TDBROpcDiffTest.scala | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala new file mode 100644 index 000000000..180e8b973 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala @@ -0,0 +1,79 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Ints, Longs} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, + ContractLocalVariableIndexOutOfRange} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.Left + +class TDBROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + property("test TDBR opcs") { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + TDBROpcDiff.max(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( + Left(ContractDataTypeMismatch)) + TDBROpcDiff.max(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), Seq.empty, 1) should be ( + Left(ContractLocalVariableIndexOutOfRange)) + TDBROpcDiff.max(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractInvalidTokenIndex)) + + TDBROpcDiff.total(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( + Left(ContractDataTypeMismatch)) + TDBROpcDiff.total(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), Seq.empty, 1) should be ( + Left(ContractLocalVariableIndexOutOfRange)) + TDBROpcDiff.total(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractInvalidTokenIndex)) + + TDBROpcDiff.unity(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( + Left(ContractDataTypeMismatch)) + TDBROpcDiff.unity(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), Seq.empty, 1) should be ( + Left(ContractLocalVariableIndexOutOfRange)) + TDBROpcDiff.unity(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractInvalidTokenIndex)) + + TDBROpcDiff.desc(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( + Left(ContractDataTypeMismatch)) + TDBROpcDiff.desc(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), Seq.empty, 1) should be ( + Left(ContractLocalVariableIndexOutOfRange)) + TDBROpcDiff.desc(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( + Left(ContractInvalidTokenIndex)) + } +} From 395b8fa05a528a63c13b287e8425cfd56eed84b3 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 5 Aug 2020 11:43:03 +0800 Subject: [PATCH 032/391] add SystemtransferDiffTest --- .../opcdiffs/SystemTransferDiffTest.scala | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala new file mode 100644 index 000000000..416c7784a --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala @@ -0,0 +1,101 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Ints, Longs} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.{ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidAmount, + ContractTokenBalanceInsufficient, GenericError, InvalidContractAddress} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.{Left, Right} + +class SystemTransferDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { + + val state = newState() + + val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L) + + property("test system transfer opcs") { + SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( + Right(OpcDiff.empty)) + SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( + Left(InvalidContractAddress)) + SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( + Right(OpcDiff.empty)) + SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, + DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( + Left(InvalidContractAddress)) + SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 3) should be ( + Left(GenericError("Invalid Call Index"))) + SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(0), DataType.Int32), CallType.Function, 1) should be ( + Left(GenericError("Invalid Call Type"))) + + SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( + Left(ContractDataTypeMismatch)) + SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(1), DataType.Amount)) should be ( + Left(ContractTokenBalanceInsufficient)) + SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(-1), DataType.Amount)) should be ( + Left(ContractInvalidAmount)) + SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)).right.get.relatedAddress( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress) shouldEqual true + SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx.right.get).right.get)(DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(Longs.toByteArray(0), DataType.Amount)).right.get.portfolios( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress).balance shouldEqual 0 + } +} From 7400ed992751e0352b964b5ba1aca6ef4542f56c Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 11 Aug 2020 16:11:05 +0800 Subject: [PATCH 033/391] delete txGen ext --- .../vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala | 4 ++-- .../vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala | 7 ++++--- .../vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala | 4 ++-- .../vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala | 7 ++++--- .../blockchain/state/opcdiffs/CompareOpcDiffTest.scala | 3 +-- .../vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala | 4 ++-- .../vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala | 4 ++-- .../blockchain/state/opcdiffs/SystemTransferDiffTest.scala | 4 ++-- .../vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala | 4 ++-- .../vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala | 4 ++-- .../vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala | 4 ++-- .../vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala | 4 ++-- 12 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala index 9c529f126..6c22f97a2 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala @@ -6,7 +6,7 @@ import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidCaller, ContractInvalidSigner, GenericError} import vsys.blockchain.transaction.contract.RegisterContractTransaction @@ -14,7 +14,7 @@ import vsys.settings.TestFunctionalitySettings import scala.util.{Left, Right} -class AssertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class AssertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { val state = newState() diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala index 2d0315c52..1dbcce24f 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -5,12 +5,13 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.DataEntry.maxShortBytesLength -import vsys.blockchain.transaction.{TransactionGen, ValidationError} -import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractUnsupportedOPC, InvalidDataEntry} +import vsys.blockchain.transaction.ValidationError +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractUnsupportedOPC, + InvalidDataEntry} import scala.util.{Left, Right} -class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test basic opcs") { BasicOpcDiff.add( diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala index 0c33c3865..06ca6ba47 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala @@ -7,7 +7,7 @@ import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.ByteStr import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidStateMap, ContractInvalidStateVariable, ContractMapValueInsufficient, InvalidDataEntry} import vsys.blockchain.transaction.contract.RegisterContractTransaction @@ -15,7 +15,7 @@ import vsys.settings.TestFunctionalitySettings import scala.util.Left -class CDBVOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class CDBVOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { val state = newState() diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala index 6f7fe5374..532cf4e93 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala @@ -6,14 +6,15 @@ import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} -import vsys.blockchain.transaction.ValidationError.{ContractInvalidStateMap, ContractLocalVariableIndexOutOfRange, ContractStateMapNotDefined, ContractStateVariableNotDefined} +import vsys.blockchain.transaction.TransactionParser +import vsys.blockchain.transaction.ValidationError.{ContractInvalidStateMap, ContractLocalVariableIndexOutOfRange, + ContractStateMapNotDefined, ContractStateVariableNotDefined} import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings import scala.util.Left -class CDBVROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class CDBVROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { val state = newState() diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala index 02bbe3ead..7c583eeb1 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala @@ -4,12 +4,11 @@ import com.google.common.primitives.{Ints, Longs} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.contract.{DataEntry, DataType} -import vsys.blockchain.transaction.TransactionGen import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractUnsupportedOPC} import scala.util.{Left, Right} -class CompareOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class CompareOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test compare opcs") { CompareOpcDiff.geq(DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry( diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala index a4d49217a..924b5aff6 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala @@ -6,14 +6,14 @@ import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.ContractLocalVariableIndexOutOfRange import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings import scala.util.{Left, Right} -class LoadOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class LoadOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test load opcs") { diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala index d779de1b0..8d71e292a 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/ReturnOpcDiffTest.scala @@ -6,14 +6,14 @@ import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.ContractUnsupportedOPC import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings import scala.util.Left -class ReturnOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class ReturnOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test return opcs") { diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala index 416c7784a..8dce793e0 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala @@ -7,7 +7,7 @@ import vsys.account.{ContractAccount, PrivateKeyAccount} import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.ByteStr import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidAmount, ContractTokenBalanceInsufficient, GenericError, InvalidContractAddress} import vsys.blockchain.transaction.contract.RegisterContractTransaction @@ -15,7 +15,7 @@ import vsys.settings.TestFunctionalitySettings import scala.util.{Left, Right} -class SystemTransferDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class SystemTransferDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { val state = newState() diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala index b119fde8b..3ebede987 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala @@ -7,7 +7,7 @@ import vsys.account.{ContractAccount, PrivateKeyAccount} import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.ByteStr import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, GenericError, InvalidContractAddress} import vsys.blockchain.transaction.contract.RegisterContractTransaction @@ -15,7 +15,7 @@ import vsys.settings.TestFunctionalitySettings import scala.util.{Left, Right} -class TDBAOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class TDBAOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test TDBA opcs") { diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala index 36b86089a..79e1c4a8d 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala @@ -6,14 +6,14 @@ import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex} import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings import scala.util.Left -class TDBAROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class TDBAROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test TDBAR opcs") { diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala index 4f36f667e..f7019dbe7 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala @@ -8,7 +8,7 @@ import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.ByteStr import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, ContractInvalidTokenInfo} import vsys.blockchain.transaction.contract.RegisterContractTransaction @@ -16,7 +16,7 @@ import vsys.settings.TestFunctionalitySettings import scala.util.Left -class TDBOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class TDBOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test TDB opcs") { diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala index 180e8b973..c63348f16 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala @@ -6,7 +6,7 @@ import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} import vsys.blockchain.state.diffs.newState -import vsys.blockchain.transaction.{TransactionGen, TransactionParser} +import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, ContractLocalVariableIndexOutOfRange} import vsys.blockchain.transaction.contract.RegisterContractTransaction @@ -14,7 +14,7 @@ import vsys.settings.TestFunctionalitySettings import scala.util.Left -class TDBROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { +class TDBROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test TDBR opcs") { From e57de0be6121f5870618a0e0c549f167710ceedf Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 11 Aug 2020 17:35:57 +0800 Subject: [PATCH 034/391] pick out executionContext --- .../state/opcdiffs/AssertOpcDiffTest.scala | 34 +++++----- .../state/opcdiffs/CDBVOpcDiffTest.scala | 60 ++++++++---------- .../state/opcdiffs/CDBVROpcDiffTest.scala | 42 ++++++------- .../state/opcdiffs/LoadOpcDiffTest.scala | 60 ++++++++---------- .../opcdiffs/SystemTransferDiffTest.scala | 46 ++++++-------- .../state/opcdiffs/TDBAOpcDiffTest.scala | 62 ++++++++----------- .../state/opcdiffs/TDBAROpcDiffTest.scala | 25 ++++---- .../state/opcdiffs/TDBOpcDiffTest.scala | 37 +++++------ .../state/opcdiffs/TDBROpcDiffTest.scala | 52 +++++++--------- 9 files changed, 187 insertions(+), 231 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala index 6c22f97a2..275de1f5d 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala @@ -5,6 +5,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.StateWriterImpl import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidCaller, @@ -16,7 +17,16 @@ import scala.util.{Left, Right} class AssertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { - val state = newState() + val state: StateWriterImpl = newState() + + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L).right.get + + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get property("test assert opcs") { AssertOpcDiff.assertTrue(DataEntry(Array(1.toByte), DataType.Boolean)) should be (Right(OpcDiff.empty)) @@ -61,33 +71,23 @@ class AssertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrive s"${DataEntry(Longs.toByteArray(1), DataType.Amount).json} " + s"is not equal to ${DataEntry(Ints.toByteArray(1), DataType.Int32).json}"))) - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), - ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) - - AssertOpcDiff.isCallerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + AssertOpcDiff.isCallerOrigin(executionContext)( DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address)) should be (Right(OpcDiff.empty)) - AssertOpcDiff.isCallerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + AssertOpcDiff.isCallerOrigin(executionContext)( DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.ContractAccount)) should be (Left(ContractDataTypeMismatch)) - AssertOpcDiff.isCallerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + AssertOpcDiff.isCallerOrigin(executionContext)( DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address)) should be (Left(ContractInvalidCaller)) - AssertOpcDiff.isSignerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + AssertOpcDiff.isSignerOrigin(executionContext)( DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address)) should be (Right(OpcDiff.empty)) - AssertOpcDiff.isSignerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + AssertOpcDiff.isSignerOrigin(executionContext)( DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.ContractAccount)) should be (Left(ContractDataTypeMismatch)) - AssertOpcDiff.isSignerOrigin(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + AssertOpcDiff.isSignerOrigin(executionContext)( DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address)) should be (Left(ContractInvalidSigner)) } diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala index 06ca6ba47..b7c30770d 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala @@ -5,7 +5,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} -import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.{ByteStr, StateWriterImpl} import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidStateMap, @@ -17,85 +17,77 @@ import scala.util.Left class CDBVOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { - val state = newState() + val state: StateWriterImpl = newState() - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) + "vsys", 10000L, 100, 1L).right.get + + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get property("test CDBV opcs") { - ByteStr(CDBVOpcDiff.set(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + ByteStr(CDBVOpcDiff.set(executionContext)( Array[Byte](0.toByte, 3.toByte), DataEntry( Longs.toByteArray(0), DataType.Amount)).right.get.contractDB( - ByteStr(tx.right.get.contractId.bytes.arr ++ Array[Byte](0.toByte)))) shouldEqual ByteStr(DataEntry( + ByteStr(tx.contractId.bytes.arr ++ Array[Byte](0.toByte)))) shouldEqual ByteStr(DataEntry( Longs.toByteArray(0), DataType.Amount).bytes) - CDBVOpcDiff.set(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.set(executionContext)( Array[Byte](0.toByte, 2.toByte), DataEntry( Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidStateVariable)) - ByteStr(CDBVOpcDiff.mapSet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + ByteStr(CDBVOpcDiff.mapSet(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount)).right.get.contractDB( - ByteStr(tx.right.get.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( + ByteStr(tx.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( Longs.toByteArray(0), DataType.Amount).bytes))) shouldEqual ByteStr(DataEntry( Longs.toByteArray(0), DataType.Amount).bytes) - CDBVOpcDiff.mapSet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapSet(executionContext)( Array[Byte](0.toByte, 3.toByte, 2.toByte), DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidStateMap)) - CDBVOpcDiff.mapValueAdd(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueAdd(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Longs.toByteArray(0), DataType.Amount)).right.get.contractNumDB( - ByteStr(tx.right.get.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( + ByteStr(tx.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( Longs.toByteArray(0), DataType.Amount).bytes)) shouldEqual 0 - CDBVOpcDiff.mapValueAdd(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueAdd(executionContext)( Array[Byte](0.toByte, 2.toByte, 2.toByte), DataEntry( Longs.toByteArray(0), DataType.ShortBytes), DataEntry( Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidStateMap)) - CDBVOpcDiff.mapValueAdd(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueAdd(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Longs.toByteArray(-1), DataType.Amount)) should be (Left(InvalidDataEntry)) - CDBVOpcDiff.mapValueAdd(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueAdd(executionContext)( Array[Byte](0.toByte, 3.toByte, 4.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), DataEntry( Longs.toByteArray(1), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) - CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueMinus(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Longs.toByteArray(0), DataType.Amount)).right.get.contractNumDB( - ByteStr(tx.right.get.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( + ByteStr(tx.contractId.bytes.arr ++ Array[Byte](0.toByte) ++ DataEntry( Longs.toByteArray(0), DataType.Amount).bytes)) shouldEqual 0 - CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueMinus(executionContext)( Array[Byte](0.toByte, 2.toByte, 2.toByte), DataEntry( Longs.toByteArray(0), DataType.ShortBytes), DataEntry( Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidStateMap)) - CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueMinus(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Longs.toByteArray(-1), DataType.Amount)) should be (Left(InvalidDataEntry)) - CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueMinus(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), DataEntry( Longs.toByteArray(1), DataType.Amount)) should be (Left(ContractMapValueInsufficient)) - CDBVOpcDiff.mapValueMinus(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVOpcDiff.mapValueMinus(executionContext)( Array[Byte](0.toByte, 3.toByte, 4.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), DataEntry( Longs.toByteArray(1), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala index 532cf4e93..93706cfde 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala @@ -5,6 +5,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.StateWriterImpl import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractInvalidStateMap, ContractLocalVariableIndexOutOfRange, @@ -16,58 +17,53 @@ import scala.util.Left class CDBVROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { - val state = newState() + val state: StateWriterImpl = newState() - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) + "vsys", 10000L, 100, 1L).right.get + + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get property("test CDBVR opcs") { - CDBVROpcDiff.get(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.get(executionContext)( Array[Byte](0.toByte, 3.toByte), Seq.empty, 0) should be (Left(ContractStateVariableNotDefined)) - CDBVROpcDiff.get(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.get(executionContext)( Array[Byte](0.toByte, 3.toByte), Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - CDBVROpcDiff.mapGet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.mapGet(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be ( Left(ContractStateMapNotDefined)) - CDBVROpcDiff.mapGet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.mapGet(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidStateMap)) - CDBVROpcDiff.mapGet(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.mapGet(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), Seq.empty, 1) should be ( Left(ContractLocalVariableIndexOutOfRange)) - CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.mapGetOrDefault(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be ( Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) - CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.mapGetOrDefault(executionContext)( Array[Byte](0.toByte, 9.toByte, 9.toByte), DataEntry( Longs.toByteArray(1), DataType.Timestamp), Seq.empty, 0) should be ( Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Timestamp)))) - CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.mapGetOrDefault(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidStateMap)) - CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.mapGetOrDefault(executionContext)( Array[Byte](0.toByte, 4.toByte, 4.toByte), DataEntry( Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( Left(ContractStateMapNotDefined)) - CDBVROpcDiff.mapGetOrDefault(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + CDBVROpcDiff.mapGetOrDefault(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), Seq.empty, 1) should be ( Left(ContractLocalVariableIndexOutOfRange)) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala index 924b5aff6..ddd2e53cf 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala @@ -5,6 +5,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.StateWriterImpl import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.ContractLocalVariableIndexOutOfRange @@ -15,68 +16,59 @@ import scala.util.{Left, Right} class LoadOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { - property("test load opcs") { + val state: StateWriterImpl = newState() + + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L).right.get - val state = newState() + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), - ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) + property("test load opcs") { - LoadOpcDiff.signer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.signer(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address)))) - LoadOpcDiff.signer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.signer(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - LoadOpcDiff.caller(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.caller(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address)))) - LoadOpcDiff.caller(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.caller(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - LoadOpcDiff.timestamp(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.timestamp(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( Longs.toByteArray(0), DataType.Timestamp)))) - LoadOpcDiff.timestamp(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.timestamp(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - LoadOpcDiff.lastTokenIndex(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.lastTokenIndex(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( Ints.toByteArray(-1), DataType.Int32)))) - LoadOpcDiff.lastTokenIndex(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.lastTokenIndex(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - LoadOpcDiff.transactionId(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.transactionId(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( - Shorts.toByteArray(tx.right.get.id.arr.length.toShort) ++ tx.right.get.id.arr, DataType.ShortBytes)))) - LoadOpcDiff.transactionId(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + Shorts.toByteArray(tx.id.arr.length.toShort) ++ tx.id.arr, DataType.ShortBytes)))) + LoadOpcDiff.transactionId(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - LoadOpcDiff.signerPublicKey(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.signerPublicKey(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).publicKey, DataType.PublicKey)))) - LoadOpcDiff.signerPublicKey(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.signerPublicKey(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - LoadOpcDiff.height(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.height(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( Ints.toByteArray(1), DataType.Int32)))) - LoadOpcDiff.height(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + LoadOpcDiff.height(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) } } diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala index 8dce793e0..be6206744 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala @@ -5,7 +5,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.{ContractAccount, PrivateKeyAccount} import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataType, ExecutionContext} -import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.{ByteStr, StateWriterImpl} import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidAmount, @@ -17,82 +17,76 @@ import scala.util.{Left, Right} class SystemTransferDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { - val state = newState() + val state: StateWriterImpl = newState() - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) + "vsys", 10000L, 100, 1L).right.get + + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get property("test system transfer opcs") { - SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( Right(OpcDiff.empty)) - SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( Left(InvalidContractAddress)) - SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( Right(OpcDiff.empty)) - SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, + SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( Left(InvalidContractAddress)) - SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 3) should be ( Left(GenericError("Invalid Call Index"))) - SystemTransferDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Function, 1) should be ( Left(GenericError("Invalid Call Type"))) - SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + SystemTransferDiff.transfer(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( Left(ContractDataTypeMismatch)) - SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + SystemTransferDiff.transfer(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(1), DataType.Amount)) should be ( Left(ContractTokenBalanceInsufficient)) - SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + SystemTransferDiff.transfer(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(-1), DataType.Amount)) should be ( Left(ContractInvalidAmount)) - SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + SystemTransferDiff.transfer(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)).right.get.relatedAddress( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress) shouldEqual true - SystemTransferDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + SystemTransferDiff.transfer(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)).right.get.portfolios( diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala index 3ebede987..79cf5baf2 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala @@ -5,7 +5,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.{ContractAccount, PrivateKeyAccount} import vsys.blockchain.contract.{CallType, ContractPermitted, DataEntry, DataType, ExecutionContext} -import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.{ByteStr, StateWriterImpl} import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, @@ -17,103 +17,93 @@ import scala.util.{Left, Right} class TDBAOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { - property("test TDBA opcs") { + val state: StateWriterImpl = newState() + + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L).right.get - val state = newState() + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), - ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) + property("test TDBA opcs") { - TDBAOpcDiff.deposit(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAOpcDiff.deposit(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be ( Left(ContractInvalidTokenIndex)) - TDBAOpcDiff.deposit(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAOpcDiff.deposit(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( Left(ContractDataTypeMismatch)) - TDBAOpcDiff.withdraw(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAOpcDiff.withdraw(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be ( Left(ContractInvalidTokenIndex)) - TDBAOpcDiff.withdraw(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAOpcDiff.withdraw(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( Left(ContractDataTypeMismatch)) - TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( Right(OpcDiff.empty)) - TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( Left(InvalidContractAddress)) - TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( Right(OpcDiff.empty)) - TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, + TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( Left(InvalidContractAddress)) - TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 3) should be ( Left(GenericError("Invalid Call Index"))) - TDBAOpcDiff.getTriggerCallOpcDiff(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get, OpcDiff.empty, DataEntry( + TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Function, 1) should be ( Left(GenericError("Invalid Call Type"))) - TDBAOpcDiff.contractTransfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAOpcDiff.contractTransfer(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) - TDBAOpcDiff.contractTransfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + TDBAOpcDiff.contractTransfer(executionContext)( DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidTokenIndex)) - TDBAOpcDiff.basicTransfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAOpcDiff.basicTransfer(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) - TDBAOpcDiff.basicTransfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)( + TDBAOpcDiff.basicTransfer(executionContext)( DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidTokenIndex)) - TDBAOpcDiff.transfer(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAOpcDiff.transfer(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala index 79e1c4a8d..622abfc5d 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala @@ -5,6 +5,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.StateWriterImpl import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex} @@ -15,28 +16,30 @@ import scala.util.Left class TDBAROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { - property("test TDBAR opcs") { + val state: StateWriterImpl = newState() + + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L).right.get - val state = newState() + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), - ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) + property("test TDBAR opcs") { - TDBAROpcDiff.balance(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAROpcDiff.balance(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidTokenIndex)) - TDBAROpcDiff.balance(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBAROpcDiff.balance(executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( Left(ContractDataTypeMismatch)) TDBAROpcDiff.balanceWithoutTokenIndex( - ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + executionContext)(DataEntry( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), Seq.empty, 0) should be ( Left(ContractInvalidTokenIndex)) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala index f7019dbe7..f083ca651 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBOpcDiffTest.scala @@ -6,11 +6,10 @@ import org.scalatest.{Matchers, PropSpec} import vsys.account.ContractAccount.tokenIdFromBytes import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} -import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.{ByteStr, StateWriterImpl} import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser -import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, - ContractInvalidTokenInfo} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, ContractInvalidTokenInfo} import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings @@ -20,45 +19,41 @@ class TDBOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPr property("test TDB opcs") { - val state = newState() + val state: StateWriterImpl = newState() - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) + "vsys", 10000L, 100, 1L).right.get - val context = ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get - val tokenID: ByteStr = tokenIdFromBytes(context.contractId.bytes.arr, Ints.toByteArray(0)).right.get + val tokenID: ByteStr = tokenIdFromBytes(executionContext.contractId.bytes.arr, Ints.toByteArray(0)).right.get - TDBOpcDiff.newToken(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBOpcDiff.newToken(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Array.fill(13){1}, DataType.ShortText)) should be (Left(ContractDataTypeMismatch)) - TDBOpcDiff.newToken(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBOpcDiff.newToken(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Array.fill(13){1}, DataType.ShortText)) should be (Left(ContractInvalidTokenInfo)) - TDBOpcDiff.newToken(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBOpcDiff.newToken(executionContext)(DataEntry( Longs.toByteArray(-1), DataType.Amount), DataEntry( Longs.toByteArray(1), DataType.Amount), DataEntry( Array.fill(13){1}, DataType.ShortText)) should be (Left(ContractInvalidTokenInfo)) - TDBOpcDiff.newToken(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBOpcDiff.newToken(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), DataEntry( Longs.toByteArray(1), DataType.Amount), DataEntry( Array.fill(13){1}, DataType.ShortText)).right.get.tokenDB( ByteStr(Bytes.concat(tokenID.arr, Array(0.toByte)))) shouldEqual DataEntry( Longs.toByteArray(0), DataType.Amount).bytes - TDBOpcDiff.split(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBOpcDiff.split(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidTokenIndex)) - TDBOpcDiff.split(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBOpcDiff.split(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) } } diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala index c63348f16..590c121d1 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBROpcDiffTest.scala @@ -5,6 +5,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.account.PrivateKeyAccount import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.StateWriterImpl import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidTokenIndex, @@ -16,63 +17,56 @@ import scala.util.Left class TDBROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { - property("test TDBR opcs") { + val state: StateWriterImpl = newState() + + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L).right.get - val state = newState() + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get - val tx = RegisterContractTransaction.create(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), - ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), - "vsys", 10000L, 100, 1L) + property("test TDBR opcs") { - TDBROpcDiff.max(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.max(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( Left(ContractDataTypeMismatch)) - TDBROpcDiff.max(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.max(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), Seq.empty, 1) should be ( Left(ContractLocalVariableIndexOutOfRange)) - TDBROpcDiff.max(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.max(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidTokenIndex)) - TDBROpcDiff.total(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.total(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( Left(ContractDataTypeMismatch)) - TDBROpcDiff.total(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.total(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), Seq.empty, 1) should be ( Left(ContractLocalVariableIndexOutOfRange)) - TDBROpcDiff.total(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.total(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidTokenIndex)) - TDBROpcDiff.unity(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.unity(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( Left(ContractDataTypeMismatch)) - TDBROpcDiff.unity(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.unity(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), Seq.empty, 1) should be ( Left(ContractLocalVariableIndexOutOfRange)) - TDBROpcDiff.unity(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.unity(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidTokenIndex)) - TDBROpcDiff.desc(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.desc(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( Left(ContractDataTypeMismatch)) - TDBROpcDiff.desc(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.desc(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), Seq.empty, 1) should be ( Left(ContractLocalVariableIndexOutOfRange)) - TDBROpcDiff.desc(ExecutionContext.fromRegConTx(state, TestFunctionalitySettings.Enabled, Option(0L), - 1L, 1, tx.right.get).right.get)(DataEntry( + TDBROpcDiff.desc(executionContext)(DataEntry( Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidTokenIndex)) } From 269b8c783562b76132ef2fbe4547fa52824b4adc Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 11 Aug 2020 18:08:49 +0800 Subject: [PATCH 035/391] delete repeated key creation --- .../state/opcdiffs/AssertOpcDiffTest.scala | 24 +++++----- .../state/opcdiffs/LoadOpcDiffTest.scala | 7 ++- .../opcdiffs/SystemTransferDiffTest.scala | 46 ++++++++++-------- .../state/opcdiffs/TDBAOpcDiffTest.scala | 48 +++++++++++-------- .../state/opcdiffs/TDBAROpcDiffTest.scala | 9 ++-- 5 files changed, 76 insertions(+), 58 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala index 275de1f5d..004d135a9 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/AssertOpcDiffTest.scala @@ -28,6 +28,12 @@ class AssertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrive state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx).right.get + val account: Array[Byte] = PrivateKeyAccount( + Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr + + val account1: Array[Byte] = PrivateKeyAccount( + Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr + property("test assert opcs") { AssertOpcDiff.assertTrue(DataEntry(Array(1.toByte), DataType.Boolean)) should be (Right(OpcDiff.empty)) AssertOpcDiff.assertTrue(DataEntry(Array(0.toByte), DataType.Boolean)) should be ( @@ -72,23 +78,17 @@ class AssertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrive s"is not equal to ${DataEntry(Ints.toByteArray(1), DataType.Int32).json}"))) AssertOpcDiff.isCallerOrigin(executionContext)( - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, - DataType.Address)) should be (Right(OpcDiff.empty)) + DataEntry(account, DataType.Address)) should be (Right(OpcDiff.empty)) AssertOpcDiff.isCallerOrigin(executionContext)( - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, - DataType.ContractAccount)) should be (Left(ContractDataTypeMismatch)) + DataEntry(account, DataType.ContractAccount)) should be (Left(ContractDataTypeMismatch)) AssertOpcDiff.isCallerOrigin(executionContext)( - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, - DataType.Address)) should be (Left(ContractInvalidCaller)) + DataEntry(account1, DataType.Address)) should be (Left(ContractInvalidCaller)) AssertOpcDiff.isSignerOrigin(executionContext)( - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, - DataType.Address)) should be (Right(OpcDiff.empty)) + DataEntry(account, DataType.Address)) should be (Right(OpcDiff.empty)) AssertOpcDiff.isSignerOrigin(executionContext)( - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, - DataType.ContractAccount)) should be (Left(ContractDataTypeMismatch)) + DataEntry(account, DataType.ContractAccount)) should be (Left(ContractDataTypeMismatch)) AssertOpcDiff.isSignerOrigin(executionContext)( - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, - DataType.Address)) should be (Left(ContractInvalidSigner)) + DataEntry(account1, DataType.Address)) should be (Left(ContractInvalidSigner)) } } diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala index ddd2e53cf..ec95a52a6 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/LoadOpcDiffTest.scala @@ -27,17 +27,20 @@ class LoadOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenP state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx).right.get + val account: Array[Byte] = PrivateKeyAccount( + Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr + property("test load opcs") { LoadOpcDiff.signer(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address)))) + account, DataType.Address)))) LoadOpcDiff.signer(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) LoadOpcDiff.caller(executionContext)( Seq.empty, 0) should be (Right(Seq(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address)))) + account, DataType.Address)))) LoadOpcDiff.caller(executionContext)( Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala index be6206744..d15cea9e0 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiffTest.scala @@ -28,67 +28,73 @@ class SystemTransferDiffTest extends PropSpec with PropertyChecks with Generator state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx).right.get + val account: Array[Byte] = PrivateKeyAccount( + Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr + + val account1: Array[Byte] = PrivateKeyAccount( + Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr + property("test system transfer opcs") { SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( Right(OpcDiff.empty)) SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( Left(InvalidContractAddress)) SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( Right(OpcDiff.empty)) SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(account1, DataType.Address), DataEntry(ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( Left(InvalidContractAddress)) SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 3) should be ( Left(GenericError("Invalid Call Index"))) SystemTransferDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Function, 1) should be ( Left(GenericError("Invalid Call Type"))) SystemTransferDiff.transfer(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( Left(ContractDataTypeMismatch)) SystemTransferDiff.transfer(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(1), DataType.Amount)) should be ( Left(ContractTokenBalanceInsufficient)) SystemTransferDiff.transfer(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(-1), DataType.Amount)) should be ( Left(ContractInvalidAmount)) SystemTransferDiff.transfer(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)).right.get.relatedAddress( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress) shouldEqual true SystemTransferDiff.transfer(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)).right.get.portfolios( PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress).balance shouldEqual 0 } diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala index 79cf5baf2..b72cf8e45 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiffTest.scala @@ -28,84 +28,90 @@ class TDBAOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenP state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx).right.get + val account: Array[Byte] = PrivateKeyAccount( + Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr + + val account1: Array[Byte] = PrivateKeyAccount( + Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr + property("test TDBA opcs") { TDBAOpcDiff.deposit(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be ( Left(ContractInvalidTokenIndex)) TDBAOpcDiff.deposit(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( Left(ContractDataTypeMismatch)) TDBAOpcDiff.withdraw(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be ( Left(ContractInvalidTokenIndex)) TDBAOpcDiff.withdraw(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry(Ints.toByteArray(0), DataType.Int32)) should be ( Left(ContractDataTypeMismatch)) TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( Right(OpcDiff.empty)) TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 2) should be ( Left(InvalidContractAddress)) TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( Right(OpcDiff.empty)) TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + DataEntry(account1, DataType.Address), DataEntry(ContractAccount.fromId(ByteStr(Array.emptyByteArray)).bytes.arr, DataType.ContractAccount), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 1) should be ( Left(InvalidContractAddress)) TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Trigger, 3) should be ( Left(GenericError("Invalid Call Index"))) TDBAOpcDiff.getTriggerCallOpcDiff(executionContext, OpcDiff.empty, DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(1)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry( + account1, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( Ints.toByteArray(0), DataType.Int32), CallType.Function, 1) should be ( Left(GenericError("Invalid Call Type"))) TDBAOpcDiff.contractTransfer(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(account, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) TDBAOpcDiff.contractTransfer(executionContext)( - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(account, DataType.Address), + DataEntry(account, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidTokenIndex)) TDBAOpcDiff.basicTransfer(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(account, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) TDBAOpcDiff.basicTransfer(executionContext)( - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(account, DataType.Address), + DataEntry(account, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractInvalidTokenIndex)) TDBAOpcDiff.transfer(executionContext)(DataEntry( Longs.toByteArray(0), DataType.Amount), - DataEntry(PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + DataEntry(account, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount)) should be (Left(ContractDataTypeMismatch)) } } diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala index 622abfc5d..93e19b28b 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/TDBAROpcDiffTest.scala @@ -27,20 +27,23 @@ class TDBAROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven state, TestFunctionalitySettings.Enabled, Option(0L), 1L, 1, tx).right.get + val account: Array[Byte] = PrivateKeyAccount( + Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr + property("test TDBAR opcs") { TDBAROpcDiff.balance(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry(Ints.toByteArray(0), DataType.Int32), Seq.empty, 0) should be ( Left(ContractInvalidTokenIndex)) TDBAROpcDiff.balance(executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), DataEntry(Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be ( Left(ContractDataTypeMismatch)) TDBAROpcDiff.balanceWithoutTokenIndex( executionContext)(DataEntry( - PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)).toAddress.bytes.arr, DataType.Address), + account, DataType.Address), Seq.empty, 0) should be ( Left(ContractInvalidTokenIndex)) } From 2df9e40679090123a89babb1c8f59cd57316de52 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Tue, 25 Aug 2020 16:39:09 +0800 Subject: [PATCH 036/391] add valid atomic swap unit tests --- .../contract/swap/AtomicSwapContractGen.scala | 147 +++++++++++++++ .../swap/AtomicSwapContractDiffTest.scala | 177 ++++++++++++++++++ 2 files changed, 324 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala create mode 100644 src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala new file mode 100644 index 000000000..bb33b2ae3 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala @@ -0,0 +1,147 @@ +package vsys.blockchain.contract.swap + +import com.google.common.primitives.{Ints, Longs} +import org.scalacheck.Gen +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.account.{ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.Contract +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} +import vsys.blockchain.contract._ +import vsys.blockchain.state._ +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +trait AtomicSwapContractGen extends SystemContractGen + with TokenContractGen { + val lockIndex: Short = 0 + val solvePuzzleIndex: Short = 1 + val expireWithdrawIndex: Short = 2 + + def atomicSwapContractGen: Gen[Contract] = + ContractAtomicSwap.contract + + def initAtomicSwapContractDataStackGen(tokenId: Array[Byte]): Gen[Seq[DataEntry]] = for { + tokenId <- Gen.const(DataEntry(tokenId, DataType.TokenId)) + } yield Seq(tokenId) + + def genesisAtomicSwapGen(rep: PrivateKeyAccount, ts: Long): Gen[GenesisTransaction] = + GenesisTransaction.create(rep, ENOUGH_AMT, -1, ts).explicitGet() + + def registerAtomicSwapGen(signer: PrivateKeyAccount, contract: Contract, dataStack: Seq[DataEntry], + description: String, fee: Long, ts: Long): Gen[RegisterContractTransaction] = + RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() + + def lockAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = lockIndex + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() + } + + def solvePuzzleAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = solvePuzzleIndex + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() + } + + def expireWithdrawAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = expireWithdrawIndex + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() + } + + val atomicSwapContract: Gen[Contract] = atomicSwapContractGen + + def createAndDepositVSYSAtomicSwapContractGen(depositValue: Long): Gen[(GenesisTransaction, + GenesisTransaction, PrivateKeyAccount, PrivateKeyAccount, RegisterContractTransaction, ExecuteContractFunctionTransaction, + Long, Long, String, Array[Byte])] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + genesis <- genesisAtomicSwapGen(master, ts) + user <- accountGen + genesis2 <- genesisAtomicSwapGen(user, ts) + contract <- atomicSwapContract + description <- validDescStringGen + sysTokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + dataStack <- initAtomicSwapContractDataStackGen(sysTokenId.arr) + // Register an atomic swap contract that swaps VSYS + regContract <- registerAtomicSwapGen(master, contract, dataStack, description, fee, ts) + contractId = regContract.contractId + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + depositData = Seq(master.toAddress.bytes.arr, contractId.bytes.arr, Longs.toByteArray(depositValue)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + depositVSYS <- depositVSYSGen(master, depositData, depositType, attach, fee, ts + 1) + } yield (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) + + val tokenContract: Gen[Contract] = tokenContractGen(false) + + def createAndDepositTokenAtomicSwapContractGen(totalSupply: Long, unity: Long, issueAmount: Long, depositValue: Long): Gen[(GenesisTransaction, + GenesisTransaction, PrivateKeyAccount, PrivateKeyAccount, RegisterContractTransaction, ExecuteContractFunctionTransaction, + RegisterContractTransaction, ExecuteContractFunctionTransaction, + Long, Long, String, Array[Byte])] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + genesis <- genesisAtomicSwapGen(master, ts) + user <- accountGen + genesis2 <- genesisAtomicSwapGen(user, ts) + aContract <- atomicSwapContract + tContract <- tokenContract + description <- validDescStringGen + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + initTokenDataStack: Seq[DataEntry] <- initTokenDataStackGen(totalSupply, unity, "init") + regTokenContract <- registerTokenGen(master, tContract, initTokenDataStack, description, fee + 10000000000L, ts) + tokenContractId = regTokenContract.contractId + issueToken <- issueTokenGen(master, tokenContractId, issueAmount, attach, fee, ts + 4) + tokenId = tokenIdFromBytes(tokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + dataStack <- initAtomicSwapContractDataStackGen(tokenId.arr) + // Register an atomic swap contract that swaps Tokens + regContract <- registerAtomicSwapGen(master, aContract, dataStack, description, fee, ts) + contractId = regContract.contractId + depositData = Seq(master.toAddress.bytes.arr, contractId.bytes.arr, Longs.toByteArray(depositValue)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + depositToken <- depositTokenGen(master, tokenContractId, false, depositData, depositType, attach, fee, ts + 1) + } yield (genesis, genesis2, master, user, regTokenContract, issueToken, regContract, depositToken, ts, fee, description, attach) + + def createTwoTokenAndDepositSwapGen(totalSupply: Long, unity: Long, issueAmount: Long, depositValue: Long): Gen[(GenesisTransaction, + GenesisTransaction, PrivateKeyAccount, PrivateKeyAccount, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, Long, Long, String, Array[Byte])] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + genesis <- genesisAtomicSwapGen(master, ts) + user <- accountGen + genesis2 <- genesisAtomicSwapGen(user, ts) + tContract <- tokenContract + aContract <- atomicSwapContract + description <- validDescStringGen + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + // Register and deposit first token + initTokenDataStack: Seq[DataEntry] <- initTokenDataStackGen(totalSupply, unity, "init") + regTokenContract <- registerTokenGen(master, tContract, initTokenDataStack, description, fee + 10000000000L, ts) + tokenContractId = regTokenContract.contractId + issueToken <- issueTokenGen(master, tokenContractId, issueAmount, attach, fee, ts + 1) + tokenId = tokenIdFromBytes(tokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + swapDataStack <- initAtomicSwapContractDataStackGen(tokenId.arr) + regSwapContract <- registerAtomicSwapGen(master, aContract, swapDataStack, description, fee, ts + 2) + swapContractId = regSwapContract.contractId + depositData = Seq(master.toAddress.bytes.arr, swapContractId.bytes.arr, Longs.toByteArray(depositValue)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + depositToken <- depositTokenGen(master, tokenContractId, false, depositData, depositType, attach, fee, ts + 3) + // Register and deposit second token + initToken2DataStack: Seq[DataEntry] <- initTokenDataStackGen(totalSupply, unity, "init") + regToken2Contract <- registerTokenGen(user, tContract, initToken2DataStack, description, fee + 10000000000L, ts + 4) + token2ContractId = regToken2Contract.contractId + issueToken2 <- issueTokenGen(user, token2ContractId, issueAmount, attach, fee, ts + 5) + token2Id = tokenIdFromBytes(token2ContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + swap2DataStack <- initAtomicSwapContractDataStackGen(token2Id.arr) + regSwap2Contract <- registerAtomicSwapGen(user, aContract, swap2DataStack, description, fee, ts + 6) + swap2ContractId = regSwap2Contract.contractId + deposit2Data = Seq(user.toAddress.bytes.arr, swap2ContractId.bytes.arr, Longs.toByteArray(depositValue)) + deposit2Type = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + deposit2Token <- depositTokenGen(user, token2ContractId, false, deposit2Data, deposit2Type, attach, fee, ts + 7) + } yield (genesis, genesis2, master, user, regTokenContract, regToken2Contract, regSwapContract, regSwap2Contract, issueToken, issueToken2, + depositToken, deposit2Token, ts, fee, description, attach) +} diff --git a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala new file mode 100644 index 000000000..f5b9bad2b --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala @@ -0,0 +1,177 @@ +package vsys.blockchain.state.contract.swap + +import cats.Monoid +import com.google.common.primitives.{Bytes, Longs} +import org.scalacheck.{Gen, Shrink} +import org.scalatest.{Matchers, PropSpec} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import scorex.crypto.hash.Sha256 +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.contract._ +import vsys.blockchain.contract.swap.AtomicSwapContractGen +import vsys.blockchain.state.{ByteStr, Portfolio} +import vsys.blockchain.state.diffs.assertDiffAndStateCorrectBlockTime +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +class AtomicSwapContractDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with TokenContractGen + with SystemContractGen + with AtomicSwapContractGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsSwapContractAndSolvePuzzle: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) <- createAndDepositVSYSAtomicSwapContractGen(1000L) + lockData = Seq(Longs.toByteArray(50L), user.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regContract.contractId, lockData, lockType, attach, fee, ts) + solvePuzzleData = Seq(lock.id.arr, Longs.toByteArray(123L)) + solvePuzzleType = Seq(DataType.ShortBytes, DataType.ShortBytes) + solvePuzzle <- solvePuzzleAtomicSwapContractDataStackGen(user, regContract.contractId, solvePuzzleData, solvePuzzleType, attach, fee, ts) + } yield (genesis, genesis2, regContract, depositVSYS, lock, solvePuzzle, ts, fee) + + property("solve puzzle correctly allocates VSYS") { + forAll(preconditionsSwapContractAndSolvePuzzle) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, solve: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit))), + TestBlock.create(lock.timestamp + 1, Seq(lock, solve))) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -2 * fee + totalPortfolioDiff.effectiveBalance shouldBe -2 * fee + +// val master = reg.proofs.firstCurveProof.explicitGet().publicKey +// val user = solve.proofs.firstCurveProof.explicitGet().publicKey + val masterBytes = genesis.recipient.bytes.arr + val userBytes = genesis2.recipient.bytes.arr + val contractId = reg.contractId.bytes + + // StateVar Keys +// val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) +// val contractTokenIdKey = ByteStr(Bytes.concat(contractId.arr, Array(1.toByte))) + + // StateMap Keys + val masterBalanceInContractKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(masterBytes, DataType.Address).bytes)) + val userBalanceInContractKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(userBytes, DataType.Address).bytes)) + + newState.contractNumInfo(masterBalanceInContractKey) shouldBe 1000L - 50L // deposited - locked + newState.contractNumInfo(userBalanceInContractKey) shouldBe 50L // solving puzzle allocates the locked funds + + } + } + } + + val preconditionsSwapContractAndSolvePuzzleTokens: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regTokenContract, issueToken, regContract, depositToken, ts, fee, description, attach) <- createAndDepositTokenAtomicSwapContractGen(1000000L, 100L, 1000L, 1000L) + lockData = Seq(Longs.toByteArray(50L), user.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regContract.contractId, lockData, lockType, attach, fee, ts) + solvePuzzleData = Seq(lock.id.arr, Longs.toByteArray(123L)) + solvePuzzleType = Seq(DataType.ShortBytes, DataType.ShortBytes) + solvePuzzle <- solvePuzzleAtomicSwapContractDataStackGen(user, regContract.contractId, solvePuzzleData, solvePuzzleType, attach, fee, ts) + } yield (genesis, genesis2, regTokenContract, issueToken, regContract, depositToken, lock, solvePuzzle, ts, fee) + + property("solve puzzle correctly allocates tokens") { + forAll(preconditionsSwapContractAndSolvePuzzleTokens) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, + regToken: RegisterContractTransaction, issue: ExecuteContractFunctionTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, solve: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(regToken, issue, reg, deposit))), + TestBlock.create(lock.timestamp + 1, Seq(lock, solve))) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -2 * fee + totalPortfolioDiff.effectiveBalance shouldBe -2 * fee + +// val master = reg.proofs.firstCurveProof.explicitGet().publicKey +// val user = solve.proofs.firstCurveProof.explicitGet().publicKey + val masterBytes = genesis.recipient.bytes.arr + val userBytes = genesis2.recipient.bytes.arr + val contractId = reg.contractId.bytes + + // StateVar Keys +// val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) +// val contractTokenIdKey = ByteStr(Bytes.concat(contractId.arr, Array(1.toByte))) + + // StateMap Keys + val masterBalanceInContractKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(masterBytes, DataType.Address).bytes)) + val userBalanceInContractKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(userBytes, DataType.Address).bytes)) + + newState.contractNumInfo(masterBalanceInContractKey) shouldBe 1000L - 50L // deposited - locked + newState.contractNumInfo(userBalanceInContractKey) shouldBe 50L // solving puzzle allocates the locked funds + + } + } + } + + val preconditionsSwapContractAndSwapTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regTokenContract, regToken2Contract, regSwapContract, regSwap2Contract, issueToken, issueToken2, + depositToken, deposit2Token, ts, fee, description, attach) <- createTwoTokenAndDepositSwapGen(100000000L, 100L, 100000L, 10000L) + // Lock first swap + lockData = Seq(Longs.toByteArray(50L), user.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regSwapContract.contractId, lockData, lockType, attach, fee, ts) + solvePuzzleData = Seq(lock.id.arr, Longs.toByteArray(123L)) + solvePuzzleType = Seq(DataType.ShortBytes, DataType.ShortBytes) + solvePuzzle <- solvePuzzleAtomicSwapContractDataStackGen(user, regSwapContract.contractId, solvePuzzleData, solvePuzzleType, attach, fee, ts) + // Lock second swap + lock2Data = Seq(Longs.toByteArray(50L), master.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 50)) + lock2Type = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock2 <- lockAtomicSwapContractDataStackGen(user, regSwap2Contract.contractId, lock2Data, lock2Type, attach, fee, ts) + solvePuzzle2Data = Seq(lock2.id.arr, Longs.toByteArray(123L)) + solvePuzzle2Type = Seq(DataType.ShortBytes, DataType.ShortBytes) + solvePuzzle2 <- solvePuzzleAtomicSwapContractDataStackGen(master, regSwap2Contract.contractId, solvePuzzle2Data, solvePuzzle2Type, attach, fee, ts) + } yield (genesis, genesis2, regTokenContract, regToken2Contract, regSwapContract, regSwap2Contract, issueToken, issueToken2, + depositToken, deposit2Token, lock, lock2, solvePuzzle, solvePuzzle2, ts, fee) + + property("swap handled correctly") { + forAll(preconditionsSwapContractAndSwapTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regToken: RegisterContractTransaction, + regToken2: RegisterContractTransaction, regSwap: RegisterContractTransaction, regSwap2: RegisterContractTransaction, issue: ExecuteContractFunctionTransaction, + issue2: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, deposit2: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, + lock2: ExecuteContractFunctionTransaction, solve: ExecuteContractFunctionTransaction, solve2: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(regToken, + regToken2, regSwap, regSwap2, issue, issue2, deposit, deposit2))), + TestBlock.create(lock.timestamp + 1, Seq(lock, lock2, solve, solve2))) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -4 * fee + totalPortfolioDiff.effectiveBalance shouldBe -4 * fee + +// val master = reg.proofs.firstCurveProof.explicitGet().publicKey +// val user = solve.proofs.firstCurveProof.explicitGet().publicKey + val masterBytes = genesis.recipient.bytes.arr + val userBytes = genesis2.recipient.bytes.arr + val contractId = regSwap.contractId.bytes + val contract2Id = regSwap2.contractId.bytes + + // Contract 1 + + // StateMap Keys + val masterBalanceInContractKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(masterBytes, DataType.Address).bytes)) + val userBalanceInContractKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(userBytes, DataType.Address).bytes)) + + newState.contractNumInfo(masterBalanceInContractKey) shouldBe 10000L - 50L // deposited - locked + newState.contractNumInfo(userBalanceInContractKey) shouldBe 50L // solving puzzle allocates the locked funds + + // Contract 2 + val masterBalanceInContract2Key = ByteStr(Bytes.concat(contract2Id.arr, Array(0.toByte), DataEntry(masterBytes, DataType.Address).bytes)) + val userBalanceInContract2Key = ByteStr(Bytes.concat(contract2Id.arr, Array(0.toByte), DataEntry(userBytes, DataType.Address).bytes)) + + newState.contractNumInfo(userBalanceInContract2Key) shouldBe 10000L - 50L // deposited - locked + newState.contractNumInfo(masterBalanceInContract2Key) shouldBe 50L // solving puzzle allocates the locked funds + + } + } + } +} From 9e084d15f138a9fa0aa979708273c2f37aef848d Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Mon, 31 Aug 2020 12:17:17 +0800 Subject: [PATCH 037/391] add invalid atomic swap unit tests --- .../contract/swap/AtomicSwapContractGen.scala | 4 +- .../swap/AtomicSwapContractDiffTest.scala | 38 +++++ .../AtomicSwapContractInvalidDiffTest.scala | 148 ++++++++++++++++++ 3 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala index bb33b2ae3..d7d07b6dd 100644 --- a/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala @@ -70,12 +70,12 @@ trait AtomicSwapContractGen extends SystemContractGen sysTokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() dataStack <- initAtomicSwapContractDataStackGen(sysTokenId.arr) // Register an atomic swap contract that swaps VSYS - regContract <- registerAtomicSwapGen(master, contract, dataStack, description, fee, ts) + regContract <- registerAtomicSwapGen(master, contract, dataStack, description, fee, ts + 1) contractId = regContract.contractId attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) depositData = Seq(master.toAddress.bytes.arr, contractId.bytes.arr, Longs.toByteArray(depositValue)) depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) - depositVSYS <- depositVSYSGen(master, depositData, depositType, attach, fee, ts + 1) + depositVSYS <- depositVSYSGen(master, depositData, depositType, attach, fee, ts + 2) } yield (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) val tokenContract: Gen[Contract] = tokenContractGen(false) diff --git a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala index f5b9bad2b..991a6837b 100644 --- a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala @@ -6,6 +6,7 @@ import org.scalacheck.{Gen, Shrink} import org.scalatest.{Matchers, PropSpec} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import scorex.crypto.hash.Sha256 +import vsys.account.ContractAccount import vsys.blockchain.block.TestBlock import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} @@ -174,4 +175,41 @@ class AtomicSwapContractDiffTest extends PropSpec } } } + + val preconditionsAndWithdrawExpiredSwapVSYS: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) <- createAndDepositVSYSAtomicSwapContractGen(1000L) + lockData = Seq(Longs.toByteArray(50L), user.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regContract.contractId, lockData, lockType, attach, fee, ts) + withdrawData = Seq(lock.id.arr) + withdrawType = Seq(DataType.ShortBytes) + withdraw <- expireWithdrawAtomicSwapContractDataStackGen(master, regContract.contractId, withdrawData, withdrawType, attach, fee, ts) + withdrawVSYSData = Seq(regContract.contractId.bytes.arr, master.toAddress.bytes.arr, Longs.toByteArray(1000L)) + withdrawVSYSType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + withdrawVSYS <- withdrawVSYSGen(master, withdrawVSYSData, withdrawVSYSType, attach, fee, ts) + } yield (genesis, genesis2, regContract, depositVSYS, lock, withdraw, withdrawVSYS, ts, fee) + + property("expired swap allows withdrawal") { + forAll(preconditionsAndWithdrawExpiredSwapVSYS) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction, + withdrawVSYS: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit))), + TestBlock.create(lock.timestamp + 101, Seq(lock, withdraw, withdrawVSYS))) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -3 * fee + totalPortfolioDiff.effectiveBalance shouldBe -3 * fee + + val masterBytes = genesis.recipient.bytes.arr + val contractId = reg.contractId.bytes + + // StateMap Keys + val masterBalanceInContractKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(masterBytes, DataType.Address).bytes)) + + newState.contractNumInfo(masterBalanceInContractKey) shouldBe 0L + } + } + } } diff --git a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala new file mode 100644 index 000000000..84e3244d7 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala @@ -0,0 +1,148 @@ +package vsys.blockchain.state.contract.swap + +//import cats.Monoid +import com.google.common.primitives.Longs +import org.scalacheck.{Gen, Shrink} +import org.scalatest.{Matchers, PropSpec} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import scorex.crypto.hash.Sha256 +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.contract._ +import vsys.blockchain.contract.swap.AtomicSwapContractGen +import vsys.blockchain.state.diffs.assertDiffAndStateCorrectBlockTime +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +class AtomicSwapContractInvalidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with TokenContractGen + with SystemContractGen + with AtomicSwapContractGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndAtomicSwapInsufficientDepositedAmountInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) <- createAndDepositVSYSAtomicSwapContractGen(1000L) + lockData = Seq(Longs.toByteArray(1001L), user.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regContract.contractId, lockData, lockType, attach, fee, ts) + } yield (genesis, genesis2, regContract, depositVSYS, lock, ts, fee) + + property("unable to lock more than deposited") { + forAll(preconditionsAndAtomicSwapInsufficientDepositedAmountInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit))), + TestBlock.createWithTxStatus(lock.timestamp + 1, Seq(lock), TransactionStatus.ContractMapValueInsufficient)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + } + } + + val preconditionsAndAtomicSwapExpiredWithdrawInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) <- createAndDepositVSYSAtomicSwapContractGen(1000L) + lockData = Seq(Longs.toByteArray(1000L), user.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regContract.contractId, lockData, lockType, attach, fee, ts) + withdrawData = Seq(lock.id.arr) + withdrawType = Seq(DataType.ShortBytes) + withdraw <- expireWithdrawAtomicSwapContractDataStackGen(master, regContract.contractId, withdrawData, withdrawType, attach, fee, ts) + } yield (genesis, genesis2, regContract, depositVSYS, lock, withdraw, ts, fee) + + property("unable to withdraw before lock expires") { + forAll(preconditionsAndAtomicSwapExpiredWithdrawInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit, lock))), + TestBlock.createWithTxStatus(lock.timestamp + 99, Seq(withdraw), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsAndAtomicSwapLockWrongAddressInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) <- createAndDepositVSYSAtomicSwapContractGen(1000L) + lockData = Seq(Longs.toByteArray(1000L), user.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(user, regContract.contractId, lockData, lockType, attach, fee, ts + 3) + } yield (genesis, genesis2, regContract, depositVSYS, lock, ts, fee) + + property("wrong address cannot lock contract") { + forAll(preconditionsAndAtomicSwapLockWrongAddressInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit))), + TestBlock.createWithTxStatus(lock.timestamp + 1, Seq(lock), TransactionStatus.ContractMapValueInsufficient)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + } + } + + val preconditionsAndAtomicSwapSolvePuzzleWrongAddressInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) <- createAndDepositVSYSAtomicSwapContractGen(1000L) + lockData = Seq(Longs.toByteArray(1000L), master.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regContract.contractId, lockData, lockType, attach, fee, ts) + solvePuzzleData = Seq(lock.id.arr, Longs.toByteArray(123L)) + solvePuzzleType = Seq(DataType.ShortBytes, DataType.ShortBytes) + solvePuzzle <- solvePuzzleAtomicSwapContractDataStackGen(user, regContract.contractId, solvePuzzleData, solvePuzzleType, attach, fee, ts) + } yield (genesis, genesis2, regContract, depositVSYS, lock, solvePuzzle, ts, fee) + + property("wrong address cannot solve puzzle") { + forAll(preconditionsAndAtomicSwapSolvePuzzleWrongAddressInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, solvePuzzle: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit, lock))), + TestBlock.createWithTxStatus(lock.timestamp + 1, Seq(solvePuzzle), TransactionStatus.ContractInvalidCaller)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + } + } + + val preconditionsAndAtomicSwapSolvePuzzleExpiredInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) <- createAndDepositVSYSAtomicSwapContractGen(1000L) + lockData = Seq(Longs.toByteArray(1000L), master.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regContract.contractId, lockData, lockType, attach, fee, ts) + solvePuzzleData = Seq(lock.id.arr, Longs.toByteArray(123L)) + solvePuzzleType = Seq(DataType.ShortBytes, DataType.ShortBytes) + solvePuzzle <- solvePuzzleAtomicSwapContractDataStackGen(user, regContract.contractId, solvePuzzleData, solvePuzzleType, attach, fee, ts) + } yield (genesis, genesis2, regContract, depositVSYS, lock, solvePuzzle, ts, fee) + + property("puzzle cannot be solved after the lock expires") { + forAll(preconditionsAndAtomicSwapSolvePuzzleExpiredInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, solvePuzzle: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit, lock))), + TestBlock.createWithTxStatus(lock.timestamp + 101, Seq(solvePuzzle), TransactionStatus.ContractInvalidCaller)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + } + } + + val preconditionsAndAtomicSwapSolvePuzzleInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long)] = for { + (genesis, genesis2, master, user, regContract, depositVSYS, ts, fee, description, attach) <- createAndDepositVSYSAtomicSwapContractGen(1000L) + lockData = Seq(Longs.toByteArray(1000L), user.toAddress.bytes.arr, Sha256(Longs.toByteArray(123L)), Longs.toByteArray(ts + 100)) + lockType = Seq(DataType.Amount, DataType.Address, DataType.ShortBytes, DataType.Timestamp) + lock <- lockAtomicSwapContractDataStackGen(master, regContract.contractId, lockData, lockType, attach, fee, ts) + solvePuzzleData = Seq(lock.id.arr, Longs.toByteArray(124L)) + solvePuzzleType = Seq(DataType.ShortBytes, DataType.ShortBytes) + solvePuzzle <- solvePuzzleAtomicSwapContractDataStackGen(user, regContract.contractId, solvePuzzleData, solvePuzzleType, attach, fee, ts) + } yield (genesis, genesis2, regContract, depositVSYS, lock, solvePuzzle, ts, fee) + + property("puzzle cannot be solved by incorrect key") { + forAll(preconditionsAndAtomicSwapSolvePuzzleInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, solvePuzzle: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit, lock))), + TestBlock.createWithTxStatus(lock.timestamp + 1, Seq(solvePuzzle), TransactionStatus.ContractInvalidHash)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidHash + } + } + } + +} \ No newline at end of file From 2a4458169d7745967d23c77a4e50e8f5a7b1b149 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Tue, 1 Sep 2020 22:53:20 +0700 Subject: [PATCH 038/391] Create matrix.yml new matrix build --- .github/workflows/matrix.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/matrix.yml diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml new file mode 100644 index 000000000..85a34f9bf --- /dev/null +++ b/.github/workflows/matrix.yml @@ -0,0 +1,21 @@ +# This matrix builds VSYS with various JDKs and will be expanded to cover many more cases. + +name: VSYS Matrix + on: + push: + jobs: + build: + strategy: + matrix: + java: [graalvm, zulu, zulu@1.08, zulu@1.11 openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: olafurpg/setup-scala@v5 + with: + java-version: ${{ matrix.java }} + - name: packageAll + run: sbt packageAll + + + From b6c40d29908367930ff3906d5024a601d16d5c93 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Tue, 1 Sep 2020 23:37:16 +0700 Subject: [PATCH 039/391] Update matrix.yml --- .github/workflows/matrix.yml | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index 85a34f9bf..78875003e 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -1,21 +1,24 @@ # This matrix builds VSYS with various JDKs and will be expanded to cover many more cases. name: VSYS Matrix - on: - push: - jobs: - build: - strategy: - matrix: +on: [push] + + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: java: [graalvm, zulu, zulu@1.08, zulu@1.11 openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: olafurpg/setup-scala@v5 - with: - java-version: ${{ matrix.java }} - - name: packageAll - run: sbt packageAll + + + steps: + - uses: actions/checkout@v1 + - uses: olafurpg/setup-scala@v5 + with: + java-version: ${{ matrix.java }} + - name: Build and Package + run: sbt packageAll From 44fa243272e3141baad062681108a3a4f93e5c00 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Tue, 1 Sep 2020 23:38:20 +0700 Subject: [PATCH 040/391] Update matrix.yml --- .github/workflows/matrix.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index 78875003e..304ba15c7 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -12,11 +12,11 @@ jobs: java: [graalvm, zulu, zulu@1.08, zulu@1.11 openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] - steps: + steps: - uses: actions/checkout@v1 - uses: olafurpg/setup-scala@v5 with: - java-version: ${{ matrix.java }} + java-version: ${{ matrix.java }} - name: Build and Package run: sbt packageAll From f3801b679e1e36d3c604f51fddab904ab06b2718 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Tue, 1 Sep 2020 23:54:58 +0700 Subject: [PATCH 041/391] Update matrix.yml --- .github/workflows/matrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index 304ba15c7..bf7139d88 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [graalvm, zulu, zulu@1.08, zulu@1.11 openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] + java: [graalvm, zulu@1.08, zulu@1.11 openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] steps: From c93066f6f9a6e8a5ceea26f050a19742099cdce1 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Wed, 2 Sep 2020 00:00:51 +0700 Subject: [PATCH 042/391] Update matrix.yml --- .github/workflows/matrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index bf7139d88..7f66fe147 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [graalvm, zulu@1.08, zulu@1.11 openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] + java: [graalvm, zulu@1.08, zulu@1.11, openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] steps: From 5232e2a8a79d0a8230bee438d313eb00499bce22 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Wed, 2 Sep 2020 00:05:50 +0700 Subject: [PATCH 043/391] Update matrix.yml continue --- .github/workflows/matrix.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index 7f66fe147..62bc195c4 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -7,6 +7,7 @@ on: [push] jobs: build: runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: java: [graalvm, zulu@1.08, zulu@1.11, openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] From 243c03f735bf1ff3962c93a74475f733e757eef3 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Wed, 2 Sep 2020 00:43:25 +0700 Subject: [PATCH 044/391] Update matrix.yml --- .github/workflows/matrix.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index 62bc195c4..3103ca7aa 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -7,19 +7,22 @@ on: [push] jobs: build: runs-on: ubuntu-latest - continue-on-error: true strategy: matrix: java: [graalvm, zulu@1.08, zulu@1.11, openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 + with: + fetch-depth: 100 + - name: Fetch tags + run: git fetch --depth=100 origin +refs/tags/*:refs/tags/* - uses: olafurpg/setup-scala@v5 with: java-version: ${{ matrix.java }} - name: Build and Package run: sbt packageAll - + From 6b19594aadc81d3fb6dcb5c204f02ccf8de8e835 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Wed, 2 Sep 2020 13:44:12 +0800 Subject: [PATCH 045/391] ensure invalid test cases don't change contract db --- .../AtomicSwapContractInvalidDiffTest.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala index 84e3244d7..fb051a729 100644 --- a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala @@ -38,6 +38,9 @@ class AtomicSwapContractInvalidDiffTest extends PropSpec deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit))), TestBlock.createWithTxStatus(lock.timestamp + 1, Seq(lock), TransactionStatus.ContractMapValueInsufficient)) { (blockDiff, newState) => + blockDiff.txsDiff.contractDB.isEmpty shouldBe true + blockDiff.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiff.txsDiff.portfolios.isEmpty shouldBe false blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } } @@ -59,6 +62,9 @@ class AtomicSwapContractInvalidDiffTest extends PropSpec deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit, lock))), TestBlock.createWithTxStatus(lock.timestamp + 99, Seq(withdraw), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.contractDB.isEmpty shouldBe true + blockDiff.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiff.txsDiff.portfolios.isEmpty shouldBe false blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed } } @@ -77,6 +83,9 @@ class AtomicSwapContractInvalidDiffTest extends PropSpec deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit))), TestBlock.createWithTxStatus(lock.timestamp + 1, Seq(lock), TransactionStatus.ContractMapValueInsufficient)) { (blockDiff, newState) => + blockDiff.txsDiff.contractDB.isEmpty shouldBe true + blockDiff.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiff.txsDiff.portfolios.isEmpty shouldBe false blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } } @@ -98,6 +107,9 @@ class AtomicSwapContractInvalidDiffTest extends PropSpec deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, solvePuzzle: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit, lock))), TestBlock.createWithTxStatus(lock.timestamp + 1, Seq(solvePuzzle), TransactionStatus.ContractInvalidCaller)) { (blockDiff, newState) => + blockDiff.txsDiff.contractDB.isEmpty shouldBe true + blockDiff.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiff.txsDiff.portfolios.isEmpty shouldBe false blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller } } @@ -119,6 +131,9 @@ class AtomicSwapContractInvalidDiffTest extends PropSpec deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, solvePuzzle: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit, lock))), TestBlock.createWithTxStatus(lock.timestamp + 101, Seq(solvePuzzle), TransactionStatus.ContractInvalidCaller)) { (blockDiff, newState) => + blockDiff.txsDiff.contractDB.isEmpty shouldBe true + blockDiff.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiff.txsDiff.portfolios.isEmpty shouldBe false blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller } } @@ -140,6 +155,9 @@ class AtomicSwapContractInvalidDiffTest extends PropSpec deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, solvePuzzle: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit, lock))), TestBlock.createWithTxStatus(lock.timestamp + 1, Seq(solvePuzzle), TransactionStatus.ContractInvalidHash)) { (blockDiff, newState) => + blockDiff.txsDiff.contractDB.isEmpty shouldBe true + blockDiff.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiff.txsDiff.portfolios.isEmpty shouldBe false blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidHash } } From 20909a28e32c4828c8a47cef2629e90bef93b362 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 6 Sep 2020 16:50:21 +0700 Subject: [PATCH 046/391] Update and rename matrix.yml to readme-build.yml build exactly like the readme --- .github/workflows/matrix.yml | 28 ---------------------------- .github/workflows/readme-build.yml | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 28 deletions(-) delete mode 100644 .github/workflows/matrix.yml create mode 100644 .github/workflows/readme-build.yml diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml deleted file mode 100644 index 3103ca7aa..000000000 --- a/.github/workflows/matrix.yml +++ /dev/null @@ -1,28 +0,0 @@ -# This matrix builds VSYS with various JDKs and will be expanded to cover many more cases. - -name: VSYS Matrix -on: [push] - - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - java: [graalvm, zulu@1.08, zulu@1.11, openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] - - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 100 - - name: Fetch tags - run: git fetch --depth=100 origin +refs/tags/*:refs/tags/* - - uses: olafurpg/setup-scala@v5 - with: - java-version: ${{ matrix.java }} - - name: Build and Package - run: sbt packageAll - - - diff --git a/.github/workflows/readme-build.yml b/.github/workflows/readme-build.yml new file mode 100644 index 000000000..6ded52af8 --- /dev/null +++ b/.github/workflows/readme-build.yml @@ -0,0 +1,25 @@ +# This matrix builds VSYS with various JDKs and will be expanded to cover many more cases. + +name: Build VSYS +on: [push,pull_request] + + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: install scala + run: | + echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list + sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823 + sudo apt-get update + sudo apt-get install sbt + + - uses: actions/checkout@v2 + + - name: Build and Package + run: sbt packageAll + + + From 89200210eb8c97aacac47ca57a5ee74ea9ce2128 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 6 Sep 2020 16:52:09 +0700 Subject: [PATCH 047/391] Update readme-build.yml --- .github/workflows/readme-build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/readme-build.yml b/.github/workflows/readme-build.yml index 6ded52af8..b6eb75b0f 100644 --- a/.github/workflows/readme-build.yml +++ b/.github/workflows/readme-build.yml @@ -3,7 +3,6 @@ name: Build VSYS on: [push,pull_request] - jobs: build: runs-on: ubuntu-latest @@ -14,7 +13,7 @@ jobs: echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823 sudo apt-get update - sudo apt-get install sbt + sudo apt-get install -y sbt - uses: actions/checkout@v2 From db77bf72f4d019796655ea78ce957a5445cb2531 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Tue, 8 Sep 2020 23:30:44 +0700 Subject: [PATCH 048/391] Update plugins.sbt http -> https upstream disabled http for security reasons --- project/plugins.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index b66f6a985..1df1fb741 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,6 +1,6 @@ resolvers ++= Seq( - "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/", - "Artima Maven Repository" at "http://repo.artima.com/releases", + "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/", + "Artima Maven Repository" at "https://repo.artima.com/releases", "JBoss" at "https://repository.jboss.org", Resolver.sbtPluginRepo("releases") ) From 69beb46d741d91cdd89084218401a99864508e50 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Wed, 9 Sep 2020 02:53:50 +0700 Subject: [PATCH 049/391] Rename readme-build.yml to build.yml --- .github/workflows/{readme-build.yml => build.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{readme-build.yml => build.yml} (100%) diff --git a/.github/workflows/readme-build.yml b/.github/workflows/build.yml similarity index 100% rename from .github/workflows/readme-build.yml rename to .github/workflows/build.yml From efc134f0e307013cab676d05a5b608047565f6c9 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Wed, 9 Sep 2020 02:57:03 +0700 Subject: [PATCH 050/391] Create matrix.yml --- .github/workflows/matrix.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/matrix.yml diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml new file mode 100644 index 000000000..df5e5f7d0 --- /dev/null +++ b/.github/workflows/matrix.yml @@ -0,0 +1,21 @@ +# This matrix builds VSYS with various JDKs and will be expanded to cover many more cases. + +name: VSYS Matrix +on: [push] + + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + java: [graalvm, zulu@1.08, zulu@1.11, openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] + + + steps: + - uses: actions/checkout@v1 + - uses: olafurpg/setup-scala@v5 + with: + java-version: ${{ matrix.java }} + - name: Build and Package + run: sbt packageAll From bf9b3b695c7399330b5a9a9cd35ba6c7a696112b Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Wed, 9 Sep 2020 03:20:21 +0700 Subject: [PATCH 051/391] Delete matrix.yml --- .github/workflows/matrix.yml | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 .github/workflows/matrix.yml diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml deleted file mode 100644 index df5e5f7d0..000000000 --- a/.github/workflows/matrix.yml +++ /dev/null @@ -1,21 +0,0 @@ -# This matrix builds VSYS with various JDKs and will be expanded to cover many more cases. - -name: VSYS Matrix -on: [push] - - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - java: [graalvm, zulu@1.08, zulu@1.11, openjdk@1.14, openjdk@1.13, openjdk@1.11, openjdk@1.8, openjdk@1.12] - - - steps: - - uses: actions/checkout@v1 - - uses: olafurpg/setup-scala@v5 - with: - java-version: ${{ matrix.java }} - - name: Build and Package - run: sbt packageAll From b9b9c107e62c39df8380b745cbfc58dd90facc9c Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 9 Sep 2020 10:58:48 +0800 Subject: [PATCH 052/391] fix bug --- .../state/opcdiffs/BasicOpcDiff.scala | 281 ++++++++++-------- 1 file changed, 157 insertions(+), 124 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 498e3a184..4bba0e997 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -11,172 +11,205 @@ object BasicOpcDiff extends OpcDiffer { def add(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - if (x.dataType == DataType.Int32) { - val xValue = Ints.fromByteArray(x.data) - val yValue = Ints.fromByteArray(y.data) - if (Try(Math.addExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Ints.toByteArray(xValue + yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } else { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (Try(Math.addExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Longs.toByteArray(xValue + yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + if (pointer > dataStack.length || pointer < 0) { + Left(ContractLocalVariableIndexOutOfRange) + } else { + if (x.dataType == y.dataType) { + val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) + supportList.find(a => a == x.dataType) match { + case Some(_) => { + if (x.dataType == DataType.Int32) { + val xValue = Ints.fromByteArray(x.data) + val yValue = Ints.fromByteArray(y.data) + if (Try(Math.addExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) + else { + for { + zDataEntry <- DataEntry.create(Ints.toByteArray(xValue + yValue), x.dataType) + } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + } + } else { + val xValue = Longs.fromByteArray(x.data) + val yValue = Longs.fromByteArray(y.data) + if (Try(Math.addExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) + else { + for { + zDataEntry <- DataEntry.create(Longs.toByteArray(xValue + yValue), x.dataType) + } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + } } } + case None => Left(ContractUnsupportedOPC) } - case None => Left(ContractUnsupportedOPC) - } - } else Left(ContractDataTypeMismatch) + } else Left(ContractDataTypeMismatch) + } } + def minus(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - if (x.dataType == DataType.Int32) { - val xValue = Ints.fromByteArray(x.data) - val yValue = Ints.fromByteArray(y.data) - if (Try(Math.subtractExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Ints.toByteArray(xValue - yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } else { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (Try(Math.subtractExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Longs.toByteArray(xValue - yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + if (pointer > dataStack.length || pointer < 0) { + Left(ContractLocalVariableIndexOutOfRange) + } else { + if (x.dataType == y.dataType) { + val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) + supportList.find(a => a == x.dataType) match { + case Some(_) => { + if (x.dataType == DataType.Int32) { + val xValue = Ints.fromByteArray(x.data) + val yValue = Ints.fromByteArray(y.data) + if (Try(Math.subtractExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) + else { + for { + zDataEntry <- DataEntry.create(Ints.toByteArray(xValue - yValue), x.dataType) + } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + } + } else { + val xValue = Longs.fromByteArray(x.data) + val yValue = Longs.fromByteArray(y.data) + if (Try(Math.subtractExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) + else { + for { + zDataEntry <- DataEntry.create(Longs.toByteArray(xValue - yValue), x.dataType) + } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + } } } + case None => Left(ContractUnsupportedOPC) } - case None => Left(ContractUnsupportedOPC) - } - } else Left(ContractDataTypeMismatch) + } else Left(ContractDataTypeMismatch) + } } def multiply(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - if (x.dataType == DataType.Int32) { - val xValue = Ints.fromByteArray(x.data) - val yValue = Ints.fromByteArray(y.data) - if (Try(Math.multiplyExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Ints.toByteArray(xValue * yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } else { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (Try(Math.multiplyExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Longs.toByteArray(xValue * yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + if (pointer > dataStack.length || pointer < 0) { + Left(ContractLocalVariableIndexOutOfRange) + } else { + if (x.dataType == y.dataType) { + val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) + supportList.find(a => a == x.dataType) match { + case Some(_) => { + if (x.dataType == DataType.Int32) { + val xValue = Ints.fromByteArray(x.data) + val yValue = Ints.fromByteArray(y.data) + if (Try(Math.multiplyExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) + else { + for { + zDataEntry <- DataEntry.create(Ints.toByteArray(xValue * yValue), x.dataType) + } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + } + } else { + val xValue = Longs.fromByteArray(x.data) + val yValue = Longs.fromByteArray(y.data) + if (Try(Math.multiplyExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) + else { + for { + zDataEntry <- DataEntry.create(Longs.toByteArray(xValue * yValue), x.dataType) + } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + } } } + case None => Left(ContractUnsupportedOPC) } - case None => Left(ContractUnsupportedOPC) - } - } else Left(ContractDataTypeMismatch) + } else Left(ContractDataTypeMismatch) + } } def divide(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - if (x.dataType == DataType.Int32) { - val xValue = Ints.fromByteArray(x.data) - val yValue = Ints.fromByteArray(y.data) - if (yValue == 0) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Ints.toByteArray(xValue / yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } else { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (yValue == 0) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Longs.toByteArray(xValue / yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + if (pointer > dataStack.length || pointer < 0) { + Left(ContractLocalVariableIndexOutOfRange) + } else { + if (x.dataType == y.dataType) { + val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) + supportList.find(a => a == x.dataType) match { + case Some(_) => { + if (x.dataType == DataType.Int32) { + val xValue = Ints.fromByteArray(x.data) + val yValue = Ints.fromByteArray(y.data) + if (yValue == 0) Left(ValidationError.OverflowError) + else { + for { + zDataEntry <- DataEntry.create(Ints.toByteArray(xValue / yValue), x.dataType) + } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + } + } else { + val xValue = Longs.fromByteArray(x.data) + val yValue = Longs.fromByteArray(y.data) + if (yValue == 0) Left(ValidationError.OverflowError) + else { + for { + zDataEntry <- DataEntry.create(Longs.toByteArray(xValue / yValue), x.dataType) + } yield dataStack.patch(pointer, Seq(zDataEntry), 1) + } } } + case None => Left(ContractUnsupportedOPC) } - case None => Left(ContractUnsupportedOPC) - } - } else Left(ContractDataTypeMismatch) + } else Left(ContractDataTypeMismatch) + } } def minimum(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - val xValue = if (x.dataType == DataType.Int32) Ints.fromByteArray(x.data) else Longs.fromByteArray(x.data) - val yValue = if (y.dataType == DataType.Int32) Ints.fromByteArray(y.data) else Longs.fromByteArray(y.data) - if (xValue > yValue) Right(dataStack.patch(pointer, Seq(y), 1)) - else Right(dataStack.patch(pointer, Seq(x), 1)) + if (pointer > dataStack.length || pointer < 0) { + Left(ContractLocalVariableIndexOutOfRange) + } else { + if (x.dataType == y.dataType) { + val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) + supportList.find(a => a == x.dataType) match { + case Some(_) => { + val xValue = if (x.dataType == DataType.Int32) Ints.fromByteArray(x.data) else Longs.fromByteArray(x.data) + val yValue = if (y.dataType == DataType.Int32) Ints.fromByteArray(y.data) else Longs.fromByteArray(y.data) + if (xValue > yValue) Right(dataStack.patch(pointer, Seq(y), 1)) + else Right(dataStack.patch(pointer, Seq(x), 1)) + } + case None => Left(ContractUnsupportedOPC) } - case None => Left(ContractUnsupportedOPC) - } - } else Left(ContractDataTypeMismatch) + } else Left(ContractDataTypeMismatch) + } } def maximum(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - val xValue = if (x.dataType == DataType.Int32) Ints.fromByteArray(x.data) else Longs.fromByteArray(x.data) - val yValue = if (y.dataType == DataType.Int32) Ints.fromByteArray(y.data) else Longs.fromByteArray(y.data) - if (xValue > yValue) Right(dataStack.patch(pointer, Seq(x), 1)) - else Right(dataStack.patch(pointer, Seq(y), 1)) + if (pointer > dataStack.length || pointer < 0) { + Left(ContractLocalVariableIndexOutOfRange) + } else { + if (x.dataType == y.dataType) { + val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) + supportList.find(a => a == x.dataType) match { + case Some(_) => { + val xValue = if (x.dataType == DataType.Int32) Ints.fromByteArray(x.data) else Longs.fromByteArray(x.data) + val yValue = if (y.dataType == DataType.Int32) Ints.fromByteArray(y.data) else Longs.fromByteArray(y.data) + if (xValue > yValue) Right(dataStack.patch(pointer, Seq(x), 1)) + else Right(dataStack.patch(pointer, Seq(y), 1)) + } + case None => Left(ContractUnsupportedOPC) } - case None => Left(ContractUnsupportedOPC) - } - } else Left(ContractDataTypeMismatch) + } else Left(ContractDataTypeMismatch) + } } def concat(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - for { - res <- DataEntry.create(x.data ++ y.data, DataType.ShortBytes) - } yield dataStack.patch(pointer, Seq(res), 1) + if (pointer > dataStack.length || pointer < 0) { + Left(ContractLocalVariableIndexOutOfRange) + } else { + for { + res <- DataEntry.create(x.data ++ y.data, DataType.ShortBytes) + } yield dataStack.patch(pointer, Seq(res), 1) + } } def constantGet(constant: Array[Byte], dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - DataEntry.fromBytes(constant) match { - case Right(v) => Right(dataStack.patch(pointer, Seq(v), 1)) - case Left(e) => Left(e) + if (pointer > dataStack.length || pointer < 0) { + Left(ContractLocalVariableIndexOutOfRange) + } else { + DataEntry.fromBytes(constant) match { + case Right(v) => Right(dataStack.patch(pointer, Seq(v), 1)) + case Left(e) => Left(e) + } } } From c0ae86c24f1c01f6af0a74340399d3a5cc844099 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 9 Sep 2020 10:59:14 +0800 Subject: [PATCH 053/391] add out of range test --- .../state/opcdiffs/BasicOpcDiffTest.scala | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala index 1dbcce24f..8854d0755 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -6,8 +6,8 @@ import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.DataEntry.maxShortBytesLength import vsys.blockchain.transaction.ValidationError -import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractUnsupportedOPC, - InvalidDataEntry} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractLocalVariableIndexOutOfRange, + ContractUnsupportedOPC, InvalidDataEntry} import scala.util.{Left, Right} @@ -18,6 +18,10 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(2), DataType.Amount)))) + BasicOpcDiff.add( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) BasicOpcDiff.add( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), @@ -35,6 +39,10 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) + BasicOpcDiff.minus( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) BasicOpcDiff.minus( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), @@ -52,6 +60,10 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.multiply( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) BasicOpcDiff.multiply( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), @@ -69,6 +81,10 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.divide( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) BasicOpcDiff.divide( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), @@ -86,6 +102,10 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) + BasicOpcDiff.minimum( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(0), DataType.Amount), + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) BasicOpcDiff.minimum( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), @@ -99,6 +119,10 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.maximum( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(0), DataType.Amount), + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) BasicOpcDiff.maximum( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), @@ -114,6 +138,10 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven Seq.empty, 0) should be ( Right(Seq(DataEntry.create(Longs.toByteArray(1) ++ Longs.toByteArray(1), DataType.ShortBytes).right.get))) + BasicOpcDiff.concat( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) BasicOpcDiff.concat( DataEntry(Array.fill(maxShortBytesLength){0}, DataType.ShortBytes), DataEntry(Array.fill(1){0}, DataType.ShortBytes), @@ -123,5 +151,7 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) BasicOpcDiff.constantGet(Array(DataType.Amount.id.toByte) ++ Ints.toByteArray(1), Seq.empty, 0) should be (Left(InvalidDataEntry)) + BasicOpcDiff.constantGet(Array(DataType.Amount.id.toByte) ++ Longs.toByteArray(1), + Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) } } From d55b543af9937c34b477413ce9053c08857d20c3 Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 15 Sep 2020 17:44:29 +0800 Subject: [PATCH 054/391] add IfOpcDiffTest --- .../state/opcdiffs/IfOpcDiffTest.scala | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala new file mode 100644 index 000000000..ec2d8a8d7 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala @@ -0,0 +1,51 @@ +package vsys.blockchain.state.opcdiffs + +import com.google.common.primitives.{Longs, Shorts} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.PrivateKeyAccount +import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, ExecutionContext} +import vsys.blockchain.state.StateWriterImpl +import vsys.blockchain.state.diffs.newState +import vsys.blockchain.transaction.TransactionParser +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidOPCData} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.settings.TestFunctionalitySettings + +import scala.util.{Left, Right} + +class IfOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { + + val state: StateWriterImpl = newState() + + val tx: RegisterContractTransaction = RegisterContractTransaction.create( + PrivateKeyAccount(Array.fill(TransactionParser.KeyLength)(0)), + ContractPermitted.contract, Seq(DataEntry(Longs.toByteArray(-1), DataType.Amount)), + "vsys", 10000L, 100, 1L).right.get + + val executionContext: ExecutionContext = ExecutionContext.fromRegConTx( + state, TestFunctionalitySettings.Enabled, Option(0L), + 1L, 1, tx).right.get + + property("if opcs") { + IfOpcDiff.executeOpcBlock(executionContext, + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty) should be (Left(ContractDataTypeMismatch)) + IfOpcDiff.executeOpcBlock(executionContext, + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), + Seq.empty) should be (Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()),List()))) + IfOpcDiff.executeOpcBlock(executionContext, + DataEntry(Shorts.toByteArray(1), DataType.OpcBlock), + Seq.empty) should be (Left(ContractInvalidOPCData)) + + IfOpcDiff.runCondition( + DataEntry(Array(1.toByte), DataType.Boolean) + ) should be (Right(true)) + IfOpcDiff.runCondition( + DataEntry(Array(0.toByte), DataType.Boolean) + ) should be (Right(false)) + IfOpcDiff.runCondition( + DataEntry(Longs.toByteArray(1), DataType.Amount) + ) should be (Left(ContractDataTypeMismatch)) + } +} \ No newline at end of file From 43a9f9cefeea569714a1a35c43d684ee40cfb579 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 16 Sep 2020 17:54:51 +0800 Subject: [PATCH 055/391] add parsebytes test --- .../state/opcdiffs/IfOpcDiffTest.scala | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala index ec2d8a8d7..40def462d 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala @@ -47,5 +47,38 @@ class IfOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPro IfOpcDiff.runCondition( DataEntry(Longs.toByteArray(1), DataType.Amount) ) should be (Left(ContractDataTypeMismatch)) + + IfOpcDiff.parseBytes(executionContext)( + Array[Byte](1.toByte, 0.toByte, 1.toByte), + Seq[DataEntry](DataEntry(Array(1.toByte), DataType.Boolean), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))) should be ( + Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()), + List(DataEntry(Array(1.toByte), DataType.Boolean), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))))) + IfOpcDiff.parseBytes(executionContext)( + Array[Byte](1.toByte, 0.toByte, 1.toByte), + Seq[DataEntry](DataEntry(Array(0.toByte), DataType.Boolean), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))) should be ( + Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()), + List(DataEntry(Array(0.toByte), DataType.Boolean), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))))) + IfOpcDiff.parseBytes(executionContext)( + Array[Byte](2.toByte, 0.toByte, 1.toByte, 2.toByte), + Seq[DataEntry](DataEntry(Array(1.toByte), DataType.Boolean), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))) should be ( + Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()), + List(DataEntry(Array(1.toByte), DataType.Boolean), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))))) + IfOpcDiff.parseBytes(executionContext)( + Array[Byte](2.toByte, 0.toByte, 1.toByte, 2.toByte), + Seq[DataEntry](DataEntry(Array(0.toByte), DataType.Boolean), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))) should be ( + Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()), + List(DataEntry(Array(0.toByte), DataType.Boolean), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), + DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))))) } } \ No newline at end of file From 14d768e551707a839c32ae0b4b6505ee0ce1a7d3 Mon Sep 17 00:00:00 2001 From: zl730 Date: Thu, 17 Sep 2020 16:50:50 +0800 Subject: [PATCH 056/391] add bigint datatype & refartor datatype --- .../vsys/blockchain/contract/Contract.scala | 6 +- .../vsys/blockchain/contract/DataEntry.scala | 103 +++-------- .../vsys/blockchain/contract/DataType.scala | 173 ++++++++++++++++-- .../state/opcdiffs/CDBVROpcDiff.scala | 6 +- .../contract/ContractGenHelper.scala | 4 +- .../channel/PaymentChannelContractGen.scala | 8 +- .../token/NonFungibleContractGen.scala | 6 +- .../contract/token/SystemContractGen.scala | 6 +- .../contract/token/TokenContractGen.scala | 6 +- 9 files changed, 196 insertions(+), 122 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index 6c6322abb..c08c48573 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -135,13 +135,13 @@ object Contract extends ScorexLogging { def checkStateVar(stateVar: Array[Byte]): Boolean = stateVar.length == 2 - def checkStateVar(stateVar: Array[Byte], dataType: DataType.DataTypeVal): Boolean = + def checkStateVar(stateVar: Array[Byte], dataType: DataType.DataTypeVal[_]): Boolean = stateVar.length == 2 && dataType == DataType(stateVar(1)) - def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.Value): Boolean = + def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.DataTypeVal[_]): Boolean = stateMap.length == 3 && keyDataType == DataType(stateMap(1)) - def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.DataTypeVal, valueDataType: DataType.DataTypeVal): Boolean = + def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.DataTypeVal[_], valueDataType: DataType.DataTypeVal[_]): Boolean = stateMap.length == 3 && keyDataType == DataType(stateMap(1)) && valueDataType == DataType(stateMap(2)) private def isByteArrayValid(bytes: Array[Byte], textual: Seq[Array[Byte]]): Boolean = { diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index d6e343a1e..e5e36b2d4 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -1,74 +1,47 @@ package vsys.blockchain.contract -import com.google.common.primitives.{Bytes, Ints, Longs, Shorts} -import play.api.libs.json.{JsObject, JsValue, Json} +import com.google.common.primitives.{Shorts, Bytes} +import play.api.libs.json.{JsObject, Json} import scorex.crypto.encode.Base58 -import vsys.account.{Address, AddressScheme, ContractAccount, PublicKeyAccount} -import vsys.account.ContractAccount.ChecksumLength -import vsys.blockchain.state.ByteStr import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError.InvalidDataEntry -import vsys.utils.crypto.hash.SecureCryptographicHash._ import scala.util.Success case class DataEntry(data: Array[Byte], - dataType: DataType.DataTypeVal) { + dataType: DataType.DataTypeVal[_]) { lazy val bytes: Array[Byte] = Array(dataType.id.asInstanceOf[Byte]) ++ data lazy val json: JsObject = Json.obj( - "data" -> toJson(data, dataType), + "data" -> dataType.jsonifierB(data), "type" -> dataType ) - private def toJson(d: Array[Byte], t: DataType.DataTypeVal): JsValue = { - t match { - case DataType.PublicKey => Json.toJson(PublicKeyAccount(d).address) - case DataType.Address => Json.toJson(Address.fromBytes(d).right.get.address) - case DataType.Amount => Json.toJson(Longs.fromByteArray(d)) - case DataType.Int32 => Json.toJson(Ints.fromByteArray(d)) - case DataType.ShortText => Json.toJson(Base58.encode(d)) - case DataType.ContractAccount => Json.toJson(ContractAccount.fromBytes(d).right.get.address) - case DataType.TokenId => Json.toJson(ByteStr(d).base58) - case DataType.Timestamp => Json.toJson(Longs.fromByteArray(d)) - case DataType.Boolean => Json.toJson(if (d(0) == 1.toByte) "True" else "False") - case DataType.ShortBytes => Json.toJson(Base58.encode(d)) - case DataType.OpcBlock => Json.toJson("Internal code block") - case _ => Json.toJson("Unsupported data type") - } - } - override def equals(obj: Any): Boolean = obj match { - case a: DataEntry => bytes sameElements a.bytes + case a: DataEntry => (bytes sameElements a.bytes) && DataType.check(dataType.id.toByte, a.dataType.id.toByte) case _ => false } - override def hashCode(): Int = java.util.Arrays.hashCode(bytes) + override def hashCode(): Int = java.util.Arrays.hashCode(Array(dataType.id.toByte) ++ bytes) } object DataEntry { - private def scheme = AddressScheme.current + def create(data: Array[Byte], dataType: DataType.DataTypeVal[_]): Either[ValidationError, DataEntry] = + if (dataType.lenFixed || dataType == DataType.Account) doCreate(data, dataType) + else doCreate(DataType.arrayShortLengthToByteArray(data) ++ data, dataType) - def create(data: Array[Byte], dataType: DataType.DataTypeVal): Either[ValidationError, DataEntry] = { - dataType match { - case DataType.ShortText if checkDataType(Shorts.toByteArray(data.length.toShort) ++ data, dataType) => Right(DataEntry(Shorts.toByteArray(data.length.toShort) ++ data, dataType)) - case DataType.ShortBytes if checkDataType(Shorts.toByteArray(data.length.toShort) ++ data, dataType) => Right(DataEntry(Shorts.toByteArray(data.length.toShort) ++ data, dataType)) - case _ if checkDataType(data, dataType) => Right(DataEntry(data, dataType)) - case _ => Left(InvalidDataEntry) - } - } + // length unfixed data array should start with 2 bytes which indicates length of content of data + private def doCreate(data: Array[Byte], dataType: DataType.DataTypeVal[_]): Either[ValidationError, DataEntry] = + if (dataType.validator(data)) Right(DataEntry(data, dataType)) else Left(InvalidDataEntry) def fromBytes(bytes: Array[Byte]): Either[ValidationError, DataEntry] = { - if (bytes.length == 0 || DataType.fromByte(bytes(0)).isEmpty) - Left(InvalidDataEntry) - else - DataType.fromByte(bytes(0)) match { - case Some(DataType.ShortText) => create(bytes.drop(3), DataType.ShortText) - case Some(DataType.ShortBytes) => create(bytes.drop(3), DataType.ShortBytes) - case _ => create(bytes.tail, DataType(bytes(0)).asInstanceOf[DataType.DataTypeVal]) + + if (bytes.length == 0) Left(InvalidDataEntry) else DataType.fromByte(bytes(0)) match { + case Some(dt) => doCreate(bytes.tail, dt) + case _ => Left(InvalidDataEntry) } } @@ -83,16 +56,17 @@ object DataEntry { bytes.headOption match { case Some(b) => DataType.fromByte(b) match { - case Some(dt: DataType.DataTypeVal) if (dt.lenFixed && checkDataType(bytes.drop(1).take(dt.maxLen), dt)) => + case Some(dt: DataType.DataTypeVal[_]) if (dt.lenFixed && dt.validator(bytes.drop(1).take(dt.maxLen))) => Right((DataEntry(bytes.drop(1).take(dt.maxLen), dt), bytes.drop(1 + dt.maxLen))) - case Some(dt: DataType.DataTypeVal) if (!dt.lenFixed && dt.maxLen <= Short.MaxValue && checkDataType(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt)) => - Right((DataEntry(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt), bytes.drop(3 + Shorts.fromByteArray(bytes.drop(1).take(2))))) + case Some(dt: DataType.DataTypeVal[_]) if (!dt.lenFixed && dt.maxLen <= Short.MaxValue + && dt.validator(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))))) => + Right((DataEntry(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt), + bytes.drop(3 + Shorts.fromByteArray(bytes.drop(1).take(2))))) case _ => Left(InvalidDataEntry) } case _ => Left(InvalidDataEntry) } - } def serializeArrays(ds: Seq[DataEntry]): Array[Byte] = { @@ -111,39 +85,4 @@ object DataEntry { case Left(l) => Left(l) } } - - private def checkDataType(data: Array[Byte], dataType: DataType.DataTypeVal): Boolean = - ((dataType.lenFixed && data.length == dataType.maxLen) - || (!dataType.lenFixed && Shorts.fromByteArray(data.take(2)) == data.drop(2).length && data.drop(2).length <= dataType.maxLen)) && - (dataType match { - case DataType.Address => Address.fromBytes(data).isRight - case DataType.Amount => Longs.fromByteArray(data) >= 0 - case DataType.Int32 => Ints.fromByteArray(data) >= 0 - case DataType.ContractAccount => ContractAccount.fromBytes(data).isRight - case DataType.TokenId => isTokenIdValid(data) - case DataType.Boolean => (data(0) == 1.toByte || data(0) == 0.toByte) - case DataType.PublicKey | DataType.ShortText | DataType.Timestamp | DataType.ShortBytes | DataType.OpcBlock => true - case _ => false - }) - - private def isTokenIdValid(addressBytes: Array[Byte]): Boolean = { - val version = addressBytes.head - val network = addressBytes.tail.head - if (version != ContractAccount.TokenAddressVersion) { - false - } else if (network != scheme.chainId) { - false - } else { - if (addressBytes.length != ContractAccount.TokenAddressLength) - false - else { - val checkSum = addressBytes.takeRight(ChecksumLength) - val checkSumGenerated = calcCheckSum(addressBytes.dropRight(ChecksumLength)) - checkSum.sameElements(checkSumGenerated) - } - } - } - - private def calcCheckSum(withoutChecksum: Array[Byte]): Array[Byte] = hash(withoutChecksum).take(ChecksumLength) - } diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index 59bcfea97..aceefc674 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -1,7 +1,13 @@ package vsys.blockchain.contract import vsys.blockchain.transaction.TransactionParser.{AmountLength, KeyLength, TimestampLength} - +import play.api.libs.json.{JsValue, Json} +import com.google.common.primitives.{Ints, Longs, Shorts} +import vsys.account.{AddressScheme, PublicKeyAccount} +import scorex.crypto.encode.Base58 +import vsys.account.ContractAccount.ChecksumLength +import vsys.blockchain.state.ByteStr +import vsys.utils.crypto.hash.SecureCryptographicHash._ import scala.util.Try object DataType extends Enumeration { @@ -9,26 +15,148 @@ object DataType extends Enumeration { val MaxShortTextLength = 140 val MaxShortBytesLength = 255 val MaxOpcBlockLength = 255 + val MaxBigIntLength = 255 // less than 1024 bits + + sealed case class DataTypeVal[T](dataType: Int, lenFixed: Boolean, maxLen: Int, + deserializer: Array[Byte] => T, + serializer: T => Array[Byte], + jsonifier: T => JsValue, + private val extValidator: Array[Byte] => Boolean) extends Val(dataType) { + + def *(n: Int): Int = n * dataType + + val jsonifierB: Array[Byte] => JsValue = b => jsonifier(deserializer(b)) + + // check length and other limits + val validator: Array[Byte] => Boolean = data => (((lenFixed && data.length == maxLen) + || (!lenFixed && data.length > 2 && Shorts.fromByteArray(data.take(2)) == data.drop(2).length && data.drop(2).length <= maxLen)) + && extValidator(data)) + } + + val PublicKey = DataTypeVal(1, + lenFixed = true, + maxLen = KeyLength, + deserializer = PublicKeyAccount(_), + serializer = (p: PublicKeyAccount) => p.publicKey, + jsonifier = (p: PublicKeyAccount) => Json.toJson(p.address), + extValidator = _ => true) + + val Address = DataTypeVal(2, + lenFixed = true, + maxLen = vsys.account.Address.AddressLength, + deserializer = vsys.account.Address.fromBytes(_).right.get, + serializer = (a: vsys.account.Address) => a.bytes.arr, + jsonifier = (a: vsys.account.Address) => Json.toJson(a.address), + extValidator = vsys.account.Address.fromBytes(_).isRight) + + val Amount = DataTypeVal(3, + lenFixed = true, + maxLen = AmountLength, + deserializer = Longs.fromByteArray(_), + serializer = Longs.toByteArray(_), + jsonifier = (a: Long) => Json.toJson(a), + extValidator = Longs.fromByteArray(_) >= 0) + + val Int32 = DataTypeVal(4, + lenFixed = true, + maxLen = 4, + deserializer = Ints.fromByteArray(_), + serializer = Ints.toByteArray(_), + jsonifier = (i: Int) => Json.toJson(i), + extValidator = Ints.fromByteArray(_) >= 0) + + val ShortText = DataTypeVal(5, + lenFixed = false, + maxLen = MaxShortTextLength, + deserializer = b => new String(b.drop(2)), + serializer = (s: String) => arrayShortLengthToByteArray(s.getBytes) ++ s.getBytes, + jsonifier = (s: String) => Json.toJson(s), + extValidator = _ => true) + + val ContractAccount = DataTypeVal(6, + lenFixed = true, + maxLen = vsys.account.ContractAccount.AddressLength, + deserializer = vsys.account.ContractAccount.fromBytes(_).right.get, + serializer = (a: vsys.account.ContractAccount) => a.bytes.arr, + jsonifier = (a: vsys.account.ContractAccount) => Json.toJson(a.address), + extValidator = vsys.account.ContractAccount.fromBytes(_).isRight) - sealed case class DataTypeVal(dataType: Int, lenFixed: Boolean, maxLen: Int) extends Val(dataType) { def *(n: Int): Int = n * dataType } - - val PublicKey = DataTypeVal(1, true, KeyLength) - val Address = DataTypeVal(2, true, vsys.account.Address.AddressLength) - val Amount = DataTypeVal(3, true, AmountLength) - val Int32 = DataTypeVal(4, true, 4) - val ShortText = DataTypeVal(5, false, MaxShortTextLength) - val ContractAccount = DataTypeVal(6, true, vsys.account.ContractAccount.AddressLength) - val Account = DataTypeVal(7, false, (vsys.account.Address.AddressLength).max(vsys.account.ContractAccount.AddressLength)) - val TokenId = DataTypeVal(8, true, vsys.account.ContractAccount.TokenAddressLength) - val Timestamp = DataTypeVal(9, true, TimestampLength) - val Boolean = DataTypeVal(10, true, 1) - val ShortBytes = DataTypeVal(11, false, MaxShortBytesLength) - val Balance = DataTypeVal(12, true, AmountLength) - val OpcBlock = DataTypeVal(13, false, MaxOpcBlockLength) - - def fromByte(b: Byte): Option[DataType.DataTypeVal] = Try(DataType(b).asInstanceOf[DataTypeVal]).toOption + val Account = DataTypeVal(7, + lenFixed = false, + maxLen = (vsys.account.Address.AddressLength).max(vsys.account.ContractAccount.AddressLength), + deserializer = vsys.account.Account.fromBytes(_, 0).right.get._1, + serializer = (a: vsys.account.Account) => a.bytes.arr, + jsonifier = (a: vsys.account.Account) => Json.toJson(a.bytes.arr), + extValidator = vsys.account.Account.fromBytes(_, 0).isRight) + + val TokenId = DataTypeVal(8, + lenFixed = true, + maxLen = vsys.account.ContractAccount.TokenAddressLength, + deserializer = ByteStr(_), + serializer = (b: ByteStr) => b.arr, + jsonifier = (b: ByteStr) => Json.toJson(b.base58), + extValidator = addressBytes => { + // length is already ensured here + def scheme = AddressScheme.current + val version = addressBytes.head + val network = addressBytes.tail.head + val checkSum1 = addressBytes.takeRight(ChecksumLength) + val checkSum2 = hash((addressBytes.dropRight(ChecksumLength))).take(ChecksumLength) + // addr version && net id && checksum + version == vsys.account.ContractAccount.TokenAddressVersion && network == scheme.chainId && checkSum1.sameElements(checkSum2) + }) + + val Timestamp = DataTypeVal(9, + lenFixed = true, + maxLen = TimestampLength, + deserializer = Longs.fromByteArray(_), + serializer = Longs.toByteArray(_), + jsonifier = (t: Long) => Json.toJson(t), + extValidator = Longs.fromByteArray(_) >= 0) + + val Boolean = DataTypeVal(10, + lenFixed = true, + maxLen = 1, + deserializer = b => b.head == 1, + serializer = (b: Boolean) => Array((if(b) 1 else 0).toByte), + jsonifier = (b: Boolean) => Json.toJson(b.toString), + extValidator = b => (b(0) == 1 || b(0) == 0)) + + val ShortBytes = DataTypeVal(11, + lenFixed = false, + maxLen = MaxShortBytesLength, + deserializer = b => b.drop(2), + serializer = (b: Array[Byte]) => arrayShortLengthToByteArray(b) ++ b, + jsonifier = (b: Array[Byte]) => Json.toJson(Base58.encode(b)), + extValidator = _ => true) + + val Balance = DataTypeVal(12, + lenFixed = true, + maxLen = AmountLength, + deserializer = Longs.fromByteArray(_), + serializer = Longs.toByteArray(_), + jsonifier = (b: Long) => Json.toJson(b), + extValidator = Longs.fromByteArray(_) >= 0) + + val OpcBlock = DataTypeVal(13, + lenFixed = false, + maxLen = MaxOpcBlockLength, + deserializer = b => b.drop(2), + serializer = (b: Array[Byte]) => arrayShortLengthToByteArray(b) ++ b, + jsonifier = (b: Array[Byte]) => Json.toJson(Base58.encode(b)), + extValidator = _ => true) + + val BigInteger = DataTypeVal(14, + lenFixed = false, + maxLen = MaxBigIntLength, + deserializer = b => BigInt(b.drop(2)), + serializer = (i: BigInt) => arrayShortLengthToByteArray(i.toByteArray) ++ i.toByteArray, + jsonifier = (i: BigInt) => Json.toJson(i.toString), + extValidator = _ => true) + + def fromByte(b: Byte): Option[DataType.DataTypeVal[_]] = Try(DataType(b).asInstanceOf[DataTypeVal[_]]).toOption - private def check(a: Byte, b: Byte): Boolean = { + def check(a: Byte, b: Byte): Boolean = { if (a == b) true else if (a == DataType.Account.id) b == DataType.Address.id || b == DataType.ContractAccount.id else if (b == DataType.Account.id) check(b, a) @@ -39,4 +167,11 @@ object DataType extends Enumeration { paraTypes.length == dataTypes.length && (paraTypes, dataTypes).zipped.forall { case (a, b) => check(a, b) } } + def sqrt(y: BigInt): BigInt = { + if (y > 3) Stream.iterate((y, (y >> 1) + 1)){ case (z, x) => (x, (y / x + x) >> 1) }.dropWhile{ case(z, x) => x < z }.head._1 + else 1 + } + + def arrayShortLengthToByteArray(a: Array[_]) = Shorts.toByteArray(a.length.toShort) + } diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala index 0f58853c0..7a3781efa 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala @@ -13,7 +13,7 @@ object CDBVROpcDiff extends OpcDiffer { def get(context: ExecutionContext)(stateVar: Array[Byte], dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateVar(stateVar, DataType(stateVar(1)).asInstanceOf[DataType.DataTypeVal])) { + if (!checkStateVar(stateVar, DataType(stateVar(1)).asInstanceOf[DataType.DataTypeVal[_]])) { Left(ContractInvalidStateVariable) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) @@ -27,7 +27,7 @@ object CDBVROpcDiff extends OpcDiffer { def mapGet(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)).asInstanceOf[DataType.DataTypeVal])) { + if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)).asInstanceOf[DataType.DataTypeVal[_]])) { Left(ContractInvalidStateMap) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) @@ -42,7 +42,7 @@ object CDBVROpcDiff extends OpcDiffer { def mapGetOrDefault(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)).asInstanceOf[DataType.DataTypeVal])) { + if (!checkStateMap(stateMap, keyValue.dataType, DataType(stateMap(2)).asInstanceOf[DataType.DataTypeVal[_]])) { Left(ContractInvalidStateMap) } else if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) diff --git a/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala b/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala index ab0c835cf..28ae19d7d 100644 --- a/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala +++ b/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala @@ -73,8 +73,8 @@ object ContractGenHelper extends TransactionGen { Bytes.concat(retType, paraType) } - def dataListGen(seqDataByte: Seq[Array[Byte]], seqDataType: Seq[DataType.DataTypeVal]): Gen[Seq[DataEntry]] = - seqDataByte.zip(seqDataType).map { case (e1: Array[Byte], e2: DataType.DataTypeVal) => DataEntry.create(e1, e2).explicitGet()} + def dataListGen(seqDataByte: Seq[Array[Byte]], seqDataType: Seq[DataType.DataTypeVal[_]]): Gen[Seq[DataEntry]] = + seqDataByte.zip(seqDataType).map { case (e1: Array[Byte], e2: DataType.DataTypeVal[_]) => DataEntry.create(e1, e2).explicitGet()} def basicContractTestGen(): Gen[(PrivateKeyAccount, Long, Long)] = for { master <- accountGen diff --git a/src/test/scala/vsys/blockchain/contract/channel/PaymentChannelContractGen.scala b/src/test/scala/vsys/blockchain/contract/channel/PaymentChannelContractGen.scala index 637ebeaf5..3db0b24cd 100644 --- a/src/test/scala/vsys/blockchain/contract/channel/PaymentChannelContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/channel/PaymentChannelContractGen.scala @@ -39,7 +39,7 @@ trait PaymentChannelContractGen extends SystemContractGen description: String, fee: Long, ts: Long): Gen[RegisterContractTransaction] = RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() - def createChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def createChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = createIndex.toShort for { @@ -47,7 +47,7 @@ trait PaymentChannelContractGen extends SystemContractGen } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def updateExpiredTimeChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def updateExpiredTimeChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = updateExpiredTimeIndex.toShort for { @@ -55,7 +55,7 @@ trait PaymentChannelContractGen extends SystemContractGen } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def chargeChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def chargeChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = chargeIndex.toShort for { @@ -79,7 +79,7 @@ trait PaymentChannelContractGen extends SystemContractGen } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def executePaymentChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def executePaymentChannelGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = executePaymentIndex.toShort for { diff --git a/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractGen.scala b/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractGen.scala index 3d7cb7bab..a9aa46cf5 100644 --- a/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractGen.scala @@ -60,7 +60,7 @@ trait NonFungibleContractGen { } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def transferNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def transferNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = transferIndex for { @@ -68,7 +68,7 @@ trait NonFungibleContractGen { } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def depositNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def depositNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = depositIndex for { @@ -76,7 +76,7 @@ trait NonFungibleContractGen { } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def withdrawNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def withdrawNonFungibleGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = withdrawIndex for { diff --git a/src/test/scala/vsys/blockchain/contract/token/SystemContractGen.scala b/src/test/scala/vsys/blockchain/contract/token/SystemContractGen.scala index 40bf76c4c..029925834 100644 --- a/src/test/scala/vsys/blockchain/contract/token/SystemContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/SystemContractGen.scala @@ -27,21 +27,21 @@ trait SystemContractGen { } yield ExecuteContractFunctionTransaction.create(sender, ContractAccount.systemContractId, sysSend, data, attachment, fee, feeScale, ts).explicitGet() } - def transferVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def transferVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { for { data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) } yield ExecuteContractFunctionTransaction.create(signer, ContractAccount.systemContractId, sysTransfer, data, attachment, fee, feeScale, ts).explicitGet() } - def depositVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def depositVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { for { data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) } yield ExecuteContractFunctionTransaction.create(signer, ContractAccount.systemContractId, sysDeposit, data, attachment, fee, feeScale, ts).explicitGet() } - def withdrawVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def withdrawVSYSGen(signer: PrivateKeyAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { for { data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractGen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractGen.scala index fd728505a..e371c5f8f 100644 --- a/src/test/scala/vsys/blockchain/contract/token/TokenContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractGen.scala @@ -88,7 +88,7 @@ trait TokenContractGen { } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def transferTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def transferTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = if (split) transferIndex else (transferIndex - 1).toShort for { @@ -96,7 +96,7 @@ trait TokenContractGen { } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def depositTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def depositTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = if (split) depositIndex else (depositIndex - 1).toShort for { @@ -104,7 +104,7 @@ trait TokenContractGen { } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def withdrawTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal], + def withdrawTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, split: Boolean, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = if (split) withdrawIndex else (withdrawIndex - 1).toShort for { From 49830e715255629b676f9ee87a36d9a0c795be1a Mon Sep 17 00:00:00 2001 From: zl730 Date: Thu, 17 Sep 2020 19:48:23 +0800 Subject: [PATCH 057/391] fix datatype --- .../vsys/blockchain/contract/DataType.scala | 81 +++++++++---------- 1 file changed, 38 insertions(+), 43 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index aceefc674..d8cf5e24f 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -33,68 +33,68 @@ object DataType extends Enumeration { && extValidator(data)) } - val PublicKey = DataTypeVal(1, + val PublicKey = DataTypeVal[PublicKeyAccount](1, lenFixed = true, maxLen = KeyLength, deserializer = PublicKeyAccount(_), - serializer = (p: PublicKeyAccount) => p.publicKey, - jsonifier = (p: PublicKeyAccount) => Json.toJson(p.address), + serializer = p => p.publicKey, + jsonifier = p => Json.toJson(p.address), extValidator = _ => true) - val Address = DataTypeVal(2, + val Address = DataTypeVal[vsys.account.Address](2, lenFixed = true, maxLen = vsys.account.Address.AddressLength, deserializer = vsys.account.Address.fromBytes(_).right.get, - serializer = (a: vsys.account.Address) => a.bytes.arr, - jsonifier = (a: vsys.account.Address) => Json.toJson(a.address), + serializer = a => a.bytes.arr, + jsonifier = a => Json.toJson(a.address), extValidator = vsys.account.Address.fromBytes(_).isRight) - val Amount = DataTypeVal(3, + val Amount = DataTypeVal[Long](3, lenFixed = true, maxLen = AmountLength, deserializer = Longs.fromByteArray(_), serializer = Longs.toByteArray(_), - jsonifier = (a: Long) => Json.toJson(a), + jsonifier = Json.toJson(_), extValidator = Longs.fromByteArray(_) >= 0) - val Int32 = DataTypeVal(4, + val Int32 = DataTypeVal[Int](4, lenFixed = true, maxLen = 4, deserializer = Ints.fromByteArray(_), serializer = Ints.toByteArray(_), - jsonifier = (i: Int) => Json.toJson(i), + jsonifier = Json.toJson(_), extValidator = Ints.fromByteArray(_) >= 0) - val ShortText = DataTypeVal(5, + val ShortText = DataTypeVal[String](5, lenFixed = false, maxLen = MaxShortTextLength, deserializer = b => new String(b.drop(2)), - serializer = (s: String) => arrayShortLengthToByteArray(s.getBytes) ++ s.getBytes, - jsonifier = (s: String) => Json.toJson(s), + serializer = s => arrayShortLengthToByteArray(s.getBytes) ++ s.getBytes, + jsonifier = Json.toJson(_), extValidator = _ => true) - val ContractAccount = DataTypeVal(6, + val ContractAccount = DataTypeVal[vsys.account.ContractAccount](6, lenFixed = true, maxLen = vsys.account.ContractAccount.AddressLength, deserializer = vsys.account.ContractAccount.fromBytes(_).right.get, - serializer = (a: vsys.account.ContractAccount) => a.bytes.arr, - jsonifier = (a: vsys.account.ContractAccount) => Json.toJson(a.address), + serializer = a => a.bytes.arr, + jsonifier = a => Json.toJson(a.address), extValidator = vsys.account.ContractAccount.fromBytes(_).isRight) - val Account = DataTypeVal(7, + val Account = DataTypeVal[vsys.account.Account](7, lenFixed = false, maxLen = (vsys.account.Address.AddressLength).max(vsys.account.ContractAccount.AddressLength), deserializer = vsys.account.Account.fromBytes(_, 0).right.get._1, - serializer = (a: vsys.account.Account) => a.bytes.arr, - jsonifier = (a: vsys.account.Account) => Json.toJson(a.bytes.arr), + serializer = a => a.bytes.arr, + jsonifier = a => Json.toJson(a.bytes.arr), extValidator = vsys.account.Account.fromBytes(_, 0).isRight) - val TokenId = DataTypeVal(8, + val TokenId = DataTypeVal[ByteStr](8, lenFixed = true, maxLen = vsys.account.ContractAccount.TokenAddressLength, deserializer = ByteStr(_), - serializer = (b: ByteStr) => b.arr, - jsonifier = (b: ByteStr) => Json.toJson(b.base58), + serializer = b => b.arr, + jsonifier = b => Json.toJson(b.base58), extValidator = addressBytes => { // length is already ensured here def scheme = AddressScheme.current @@ -106,52 +106,52 @@ object DataType extends Enumeration { version == vsys.account.ContractAccount.TokenAddressVersion && network == scheme.chainId && checkSum1.sameElements(checkSum2) }) - val Timestamp = DataTypeVal(9, + val Timestamp = DataTypeVal[Long](9, lenFixed = true, maxLen = TimestampLength, deserializer = Longs.fromByteArray(_), serializer = Longs.toByteArray(_), - jsonifier = (t: Long) => Json.toJson(t), + jsonifier = Json.toJson(_), extValidator = Longs.fromByteArray(_) >= 0) - val Boolean = DataTypeVal(10, + val Boolean = DataTypeVal[Boolean](10, lenFixed = true, maxLen = 1, deserializer = b => b.head == 1, - serializer = (b: Boolean) => Array((if(b) 1 else 0).toByte), - jsonifier = (b: Boolean) => Json.toJson(b.toString), + serializer = b => Array((if(b) 1 else 0).toByte), + jsonifier = b => Json.toJson(b.toString), extValidator = b => (b(0) == 1 || b(0) == 0)) - val ShortBytes = DataTypeVal(11, + val ShortBytes = DataTypeVal[Array[Byte]](11, lenFixed = false, maxLen = MaxShortBytesLength, deserializer = b => b.drop(2), - serializer = (b: Array[Byte]) => arrayShortLengthToByteArray(b) ++ b, - jsonifier = (b: Array[Byte]) => Json.toJson(Base58.encode(b)), + serializer = b => arrayShortLengthToByteArray(b) ++ b, + jsonifier = b => Json.toJson(Base58.encode(b)), extValidator = _ => true) - val Balance = DataTypeVal(12, + val Balance = DataTypeVal[Long](12, lenFixed = true, maxLen = AmountLength, deserializer = Longs.fromByteArray(_), serializer = Longs.toByteArray(_), - jsonifier = (b: Long) => Json.toJson(b), + jsonifier = Json.toJson(_), extValidator = Longs.fromByteArray(_) >= 0) - val OpcBlock = DataTypeVal(13, + val OpcBlock = DataTypeVal[Array[Byte]](13, lenFixed = false, maxLen = MaxOpcBlockLength, deserializer = b => b.drop(2), - serializer = (b: Array[Byte]) => arrayShortLengthToByteArray(b) ++ b, - jsonifier = (b: Array[Byte]) => Json.toJson(Base58.encode(b)), + serializer = b => arrayShortLengthToByteArray(b) ++ b, + jsonifier = b => Json.toJson(Base58.encode(b)), extValidator = _ => true) - val BigInteger = DataTypeVal(14, + val BigInteger = DataTypeVal[BigInt](14, lenFixed = false, maxLen = MaxBigIntLength, deserializer = b => BigInt(b.drop(2)), - serializer = (i: BigInt) => arrayShortLengthToByteArray(i.toByteArray) ++ i.toByteArray, - jsonifier = (i: BigInt) => Json.toJson(i.toString), + serializer = i => arrayShortLengthToByteArray(i.toByteArray) ++ i.toByteArray, + jsonifier = i => Json.toJson(i.toString), extValidator = _ => true) def fromByte(b: Byte): Option[DataType.DataTypeVal[_]] = Try(DataType(b).asInstanceOf[DataTypeVal[_]]).toOption @@ -167,11 +167,6 @@ object DataType extends Enumeration { paraTypes.length == dataTypes.length && (paraTypes, dataTypes).zipped.forall { case (a, b) => check(a, b) } } - def sqrt(y: BigInt): BigInt = { - if (y > 3) Stream.iterate((y, (y >> 1) + 1)){ case (z, x) => (x, (y / x + x) >> 1) }.dropWhile{ case(z, x) => x < z }.head._1 - else 1 - } - def arrayShortLengthToByteArray(a: Array[_]) = Shorts.toByteArray(a.length.toShort) } From 9e0b102934da0bbc8f758100878125572fee689c Mon Sep 17 00:00:00 2001 From: zl730 Date: Thu, 17 Sep 2020 19:54:13 +0800 Subject: [PATCH 058/391] bisic options and sqrt for bigInt --- .../state/opcdiffs/BasicOpcDiff.scala | 241 ++++-------------- .../state/opcdiffs/BasicOpcDiffTest.scala | 112 ++++---- 2 files changed, 111 insertions(+), 242 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 4bba0e997..48d510bf0 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -1,197 +1,66 @@ package vsys.blockchain.state.opcdiffs -import com.google.common.primitives.{Ints, Longs} import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} +import vsys.blockchain.contract.DataType._ -import scala.util.{Left, Right, Try} +import scala.util.{Left, Right, Try, Success, Failure} object BasicOpcDiff extends OpcDiffer { - def add(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - if (x.dataType == DataType.Int32) { - val xValue = Ints.fromByteArray(x.data) - val yValue = Ints.fromByteArray(y.data) - if (Try(Math.addExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Ints.toByteArray(xValue + yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } else { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (Try(Math.addExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Longs.toByteArray(xValue + yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } - } - case None => Left(ContractUnsupportedOPC) + case class BiOperator(int: (Int, Int) => Try[Int], long: (Long, Long) => Try[Long], bigInt: (BigInt, BigInt) => Try[BigInt]) + val add = BiOperator((x, y) => Try(Math.addExact(x, y)), (x, y) => Try(Math.addExact(x, y)), (x, y) => Success(x + y)) + val minus = BiOperator((x, y) => Try(Math.subtractExact(x, y)), (x, y) => Try(Math.subtractExact(x, y)), (x, y) => Success(x - y)) + val multiply = BiOperator((x, y) => Try(Math.multiplyExact(x, y)), (x, y) => Try(Math.multiplyExact(x, y)), (x, y) => Success(x * y)) + val divide = BiOperator((x, y) => Try(Math.floorDiv(x, y)), (x, y) => Try(Math.floorDiv(x, y)), (x, y) => Try(x / y)) + val minimum = BiOperator((x, y) => Try(Math.min(x, y)), (x, y) => Try(Math.min(x, y)), (x, y) => Success(x.min(y))) + val maximum = BiOperator((x, y) => Try(Math.max(x, y)), (x, y) => Try(Math.max(x, y)), (x, y) => Success(x.max(y))) + + private def appendRes[T] (p: Byte, res: T, dt: DataType.DataTypeVal[T], ds: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = for { + _ <- if(dt.validator(dt.serializer(res))) Right(()) else Left(ValidationError.OverflowError) + zDataEntry <- DataEntry.create(dt.serializer(res), dt) + } yield ds.patch(p, Seq(zDataEntry), 1) + + def operation(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], + pointer: Byte, operator: BiOperator): Either[ValidationError, Seq[DataEntry]] = + if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) + else if (x.dataType == y.dataType) x.dataType match { + case Int32 => operator.int(Int32.deserializer(x.data), Int32.deserializer(y.data)) match { + case Failure(_) => Left(ValidationError.OverflowError) + case Success(res: Int) => appendRes[Int](pointer, res, Int32, dataStack) } - } else Left(ContractDataTypeMismatch) - } - } - - - def minus(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - if (x.dataType == DataType.Int32) { - val xValue = Ints.fromByteArray(x.data) - val yValue = Ints.fromByteArray(y.data) - if (Try(Math.subtractExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Ints.toByteArray(xValue - yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } else { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (Try(Math.subtractExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Longs.toByteArray(xValue - yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } - } - case None => Left(ContractUnsupportedOPC) + case Amount => operator.long(Amount.deserializer(x.data), Amount.deserializer(y.data)) match { + case Failure(_) => Left(ValidationError.OverflowError) + case Success(res: Long) => appendRes[Long](pointer, res, Amount, dataStack) } - } else Left(ContractDataTypeMismatch) - } - } - - def multiply(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - if (x.dataType == DataType.Int32) { - val xValue = Ints.fromByteArray(x.data) - val yValue = Ints.fromByteArray(y.data) - if (Try(Math.multiplyExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Ints.toByteArray(xValue * yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } else { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (Try(Math.multiplyExact(xValue, yValue)).isFailure) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Longs.toByteArray(xValue * yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } - } - case None => Left(ContractUnsupportedOPC) + case Timestamp => operator.long(Timestamp.deserializer(x.data), Timestamp.deserializer(y.data)) match { + case Failure(_) => Left(ValidationError.OverflowError) + case Success(res: Long) => appendRes[Long](pointer, res, Timestamp, dataStack) } - } else Left(ContractDataTypeMismatch) - } - } - - def divide(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - if (x.dataType == DataType.Int32) { - val xValue = Ints.fromByteArray(x.data) - val yValue = Ints.fromByteArray(y.data) - if (yValue == 0) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Ints.toByteArray(xValue / yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } else { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (yValue == 0) Left(ValidationError.OverflowError) - else { - for { - zDataEntry <- DataEntry.create(Longs.toByteArray(xValue / yValue), x.dataType) - } yield dataStack.patch(pointer, Seq(zDataEntry), 1) - } - } - } - case None => Left(ContractUnsupportedOPC) - } - } else Left(ContractDataTypeMismatch) - } - } - - def minimum(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - val xValue = if (x.dataType == DataType.Int32) Ints.fromByteArray(x.data) else Longs.fromByteArray(x.data) - val yValue = if (y.dataType == DataType.Int32) Ints.fromByteArray(y.data) else Longs.fromByteArray(y.data) - if (xValue > yValue) Right(dataStack.patch(pointer, Seq(y), 1)) - else Right(dataStack.patch(pointer, Seq(x), 1)) - } - case None => Left(ContractUnsupportedOPC) + case BigInteger => operator.bigInt(BigInteger.deserializer(x.data), BigInteger.deserializer(y.data)) match { + case Failure(_) => Left(ValidationError.OverflowError) + case Success(res: BigInt) => appendRes[BigInt](pointer, res, BigInteger, dataStack) } - } else Left(ContractDataTypeMismatch) + case _ => Left(ContractUnsupportedOPC) + } else Left(ContractDataTypeMismatch) + + def sqrt(x: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = + if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) + else x.dataType match { + case BigInteger => { + val value = BigInteger.deserializer(x.data) + if (value < 0) Left(ValidationError.OverflowError) + else appendRes[BigInt](pointer, sqrtBigInt(value), BigInteger, dataStack) + } + case _ => Left(ContractUnsupportedOPC) } - } - def maximum(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp, DataType.Int32) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - val xValue = if (x.dataType == DataType.Int32) Ints.fromByteArray(x.data) else Longs.fromByteArray(x.data) - val yValue = if (y.dataType == DataType.Int32) Ints.fromByteArray(y.data) else Longs.fromByteArray(y.data) - if (xValue > yValue) Right(dataStack.patch(pointer, Seq(x), 1)) - else Right(dataStack.patch(pointer, Seq(y), 1)) - } - case None => Left(ContractUnsupportedOPC) - } - } else Left(ContractDataTypeMismatch) - } + def sqrtBigInt(y: BigInt): BigInt = { + if (y > 3) Stream.iterate((y, (y >> 1) + 1)){ case (z, x) => (x, (y / x + x) >> 1) }.dropWhile{ case(z, x) => x < z }.head._1 + else if (y > 0) 1 else 0 } - - def concat(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def concat(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) } else { @@ -201,8 +70,7 @@ object BasicOpcDiff extends OpcDiffer { } } - def constantGet(constant: Array[Byte], dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + def constantGet(constant: Array[Byte], dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { if (pointer > dataStack.length || pointer < 0) { Left(ContractLocalVariableIndexOutOfRange) } else { @@ -220,14 +88,15 @@ object BasicOpcDiff extends OpcDiffer { differ: (Array[Byte], Seq[DataEntry]) => Either[ValidationError, Seq[DataEntry]]) extends Val(basicType) { def *(n: Int): Int = n * basicType } - val Add = basicTypeVal(1, 4, (b, d) => add(d(b(1)), d(b(2)), d, b(3))) - val Minus = basicTypeVal(2, 4, (b, d) => minus(d(b(1)), d(b(2)), d, b(3))) - val Multiply = basicTypeVal(3, 4, (b, d) => multiply(d(b(1)), d(b(2)), d, b(3))) - val Divide = basicTypeVal(4, 4, (b, d) => divide(d(b(1)), d(b(2)), d, b(3))) - val Minimum = basicTypeVal(5, 4, (b, d) => minimum(d(b(1)), d(b(2)), d, b(3))) - val Maximum = basicTypeVal(6, 4, (b, d) => maximum(d(b(1)), d(b(2)), d, b(3))) + val Add = basicTypeVal(1, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), add)) + val Minus = basicTypeVal(2, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), minus)) + val Multiply = basicTypeVal(3, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), multiply)) + val Divide = basicTypeVal(4, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), divide)) + val Minimum = basicTypeVal(5, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), minimum)) + val Maximum = basicTypeVal(6, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), maximum)) val Concat = basicTypeVal(7, 4, (b, d) => concat(d(b(1)), d(b(2)), d, b(3))) val ConstantGet = basicTypeVal(8, 2, (b, d) => constantGet(b.slice(1, b.length-1), d, b(b.length-1))) + val SqrtBigInt = basicTypeVal(9, 3, (b, d) => sqrt(d(b(1)), d, b(2))) } override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala index d080eab2b..bedf82ae0 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -13,123 +13,123 @@ import scala.util.{Left, Right} class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test basic opcs") { - BasicOpcDiff.add( + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(2), DataType.Amount)))) - BasicOpcDiff.add( + Seq.empty, 0, BasicOpcDiff.add) should be (Right(Seq(DataEntry(Longs.toByteArray(2), DataType.Amount)))) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.add( + Seq.empty, 1, BasicOpcDiff.add) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.add( + Seq.empty, 0, BasicOpcDiff.add) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.add( + Seq.empty, 0, BasicOpcDiff.add) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + Seq.empty, 0, BasicOpcDiff.add) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.minus( + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) - BasicOpcDiff.minus( + Seq.empty, 0, BasicOpcDiff.minus) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.minus( + Seq.empty, 1, BasicOpcDiff.minus) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.minus( + Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), DataEntry(Longs.toByteArray(-1), DataType.Amount), - Seq.empty, 0) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.minus( + Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.multiply( + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) - BasicOpcDiff.multiply( + Seq.empty, 0, BasicOpcDiff.multiply) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.multiply( + Seq.empty, 1, BasicOpcDiff.multiply) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.multiply( + Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), DataEntry(Longs.toByteArray(2), DataType.Amount), - Seq.empty, 0) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.multiply( + Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.divide( + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) - BasicOpcDiff.divide( + Seq.empty, 0, BasicOpcDiff.divide) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.divide( + Seq.empty, 1, BasicOpcDiff.divide) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.divide( + Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 0) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.divide( + Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.minimum( + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) - BasicOpcDiff.minimum( + Seq.empty, 0, BasicOpcDiff.minimum) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.minimum( + Seq.empty, 1, BasicOpcDiff.minimum) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.minimum( + Seq.empty, 0, BasicOpcDiff.minimum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + Seq.empty, 0, BasicOpcDiff.minimum) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.maximum( + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) - BasicOpcDiff.maximum( + Seq.empty, 0, BasicOpcDiff.maximum) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.maximum( + Seq.empty, 1, BasicOpcDiff.maximum) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.maximum( + Seq.empty, 0, BasicOpcDiff.maximum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0) should be (Left(ContractUnsupportedOPC)) + Seq.empty, 0, BasicOpcDiff.maximum) should be (Left(ContractUnsupportedOPC)) BasicOpcDiff.concat( DataEntry(Longs.toByteArray(1), DataType.Amount), From 432f47061516d978776d97fea86518469b29c433 Mon Sep 17 00:00:00 2001 From: zl730 Date: Thu, 17 Sep 2020 20:03:32 +0800 Subject: [PATCH 059/391] add comment --- src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 48d510bf0..f10034a21 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -56,6 +56,7 @@ object BasicOpcDiff extends OpcDiffer { case _ => Left(ContractUnsupportedOPC) } + // babylonian method def sqrtBigInt(y: BigInt): BigInt = { if (y > 3) Stream.iterate((y, (y >> 1) + 1)){ case (z, x) => (x, (y / x + x) >> 1) }.dropWhile{ case(z, x) => x < z }.head._1 else if (y > 0) 1 else 0 From a5085b5cf17837eeea2d243b89b719146da2e570 Mon Sep 17 00:00:00 2001 From: Icermli Date: Fri, 18 Sep 2020 14:55:43 +0800 Subject: [PATCH 060/391] give else a validation error --- .../blockchain/state/opcdiffs/IfOpcDiffTest.scala | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala index 40def462d..20e1dea41 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala @@ -66,19 +66,16 @@ class IfOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPro Array[Byte](2.toByte, 0.toByte, 1.toByte, 2.toByte), Seq[DataEntry](DataEntry(Array(1.toByte), DataType.Boolean), DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), - DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))) should be ( + DataEntry(Shorts.toByteArray(1), DataType.OpcBlock))) should be ( Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()), List(DataEntry(Array(1.toByte), DataType.Boolean), DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), - DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))))) + DataEntry(Shorts.toByteArray(1), DataType.OpcBlock))))) IfOpcDiff.parseBytes(executionContext)( Array[Byte](2.toByte, 0.toByte, 1.toByte, 2.toByte), Seq[DataEntry](DataEntry(Array(0.toByte), DataType.Boolean), DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), - DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))) should be ( - Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()), - List(DataEntry(Array(0.toByte), DataType.Boolean), - DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), - DataEntry(Shorts.toByteArray(0), DataType.OpcBlock))))) + DataEntry(Shorts.toByteArray(1), DataType.OpcBlock))) should be ( + Left(ContractInvalidOPCData)) } } \ No newline at end of file From 10aab4fc6eeed66053fb4d67aff0bdb3fe2de748 Mon Sep 17 00:00:00 2001 From: zl730 Date: Mon, 21 Sep 2020 09:57:52 +0800 Subject: [PATCH 061/391] fix bug --- src/main/scala/vsys/blockchain/contract/DataEntry.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index e5e36b2d4..a44ff90ed 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -19,11 +19,11 @@ case class DataEntry(data: Array[Byte], ) override def equals(obj: Any): Boolean = obj match { - case a: DataEntry => (bytes sameElements a.bytes) && DataType.check(dataType.id.toByte, a.dataType.id.toByte) + case a: DataEntry => (bytes sameElements a.bytes) case _ => false } - override def hashCode(): Int = java.util.Arrays.hashCode(Array(dataType.id.toByte) ++ bytes) + override def hashCode(): Int = java.util.Arrays.hashCode(bytes) } From 9b1d74a2d18074b33f83194471fedf90e17624a4 Mon Sep 17 00:00:00 2001 From: zl730 Date: Mon, 21 Sep 2020 10:00:19 +0800 Subject: [PATCH 062/391] style issue --- src/main/scala/vsys/blockchain/contract/DataEntry.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index a44ff90ed..1cd005fb7 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -19,7 +19,7 @@ case class DataEntry(data: Array[Byte], ) override def equals(obj: Any): Boolean = obj match { - case a: DataEntry => (bytes sameElements a.bytes) + case a: DataEntry => bytes sameElements a.bytes case _ => false } From 970f4f3ab47f2b202944dd74d152df68b99330a4 Mon Sep 17 00:00:00 2001 From: zl730 Date: Mon, 21 Sep 2020 12:51:20 +0800 Subject: [PATCH 063/391] fix for comments --- src/main/scala/vsys/blockchain/contract/DataEntry.scala | 2 +- src/main/scala/vsys/blockchain/contract/DataType.scala | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index 1cd005fb7..e1e355b95 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -58,7 +58,7 @@ object DataEntry { DataType.fromByte(b) match { case Some(dt: DataType.DataTypeVal[_]) if (dt.lenFixed && dt.validator(bytes.drop(1).take(dt.maxLen))) => Right((DataEntry(bytes.drop(1).take(dt.maxLen), dt), bytes.drop(1 + dt.maxLen))) - case Some(dt: DataType.DataTypeVal[_]) if (!dt.lenFixed && dt.maxLen <= Short.MaxValue + case Some(dt: DataType.DataTypeVal[_]) if (!dt.lenFixed && dt.maxLen <= Short.MaxValue && bytes.length >= 3 && dt.validator(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))))) => Right((DataEntry(bytes.drop(1).take(2 + Shorts.fromByteArray(bytes.drop(1).take(2))), dt), bytes.drop(3 + Shorts.fromByteArray(bytes.drop(1).take(2))))) diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index d8cf5e24f..5af712a6a 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -29,7 +29,7 @@ object DataType extends Enumeration { // check length and other limits val validator: Array[Byte] => Boolean = data => (((lenFixed && data.length == maxLen) - || (!lenFixed && data.length > 2 && Shorts.fromByteArray(data.take(2)) == data.drop(2).length && data.drop(2).length <= maxLen)) + || (!lenFixed && data.length >= 2 && Shorts.fromByteArray(data.take(2)) == data.drop(2).length && data.drop(2).length <= maxLen)) && extValidator(data)) } @@ -87,7 +87,7 @@ object DataType extends Enumeration { deserializer = vsys.account.Account.fromBytes(_, 0).right.get._1, serializer = a => a.bytes.arr, jsonifier = a => Json.toJson(a.bytes.arr), - extValidator = vsys.account.Account.fromBytes(_, 0).isRight) + extValidator = _ => false) // unsupported type for now. vsys.account.Account.fromBytes(_, 0).isRight) val TokenId = DataTypeVal[ByteStr](8, lenFixed = true, @@ -136,7 +136,7 @@ object DataType extends Enumeration { deserializer = Longs.fromByteArray(_), serializer = Longs.toByteArray(_), jsonifier = Json.toJson(_), - extValidator = Longs.fromByteArray(_) >= 0) + extValidator = _ => false) // unsupported type for now. Longs.fromByteArray(_) >= 0) val OpcBlock = DataTypeVal[Array[Byte]](13, lenFixed = false, From 94069fea9b198f83910d4da6ac4997b871255038 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 24 Sep 2020 13:02:55 +0800 Subject: [PATCH 064/391] add some type test --- .../vsys/blockchain/contract/DataTypeSpecification.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala b/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala index e929e8bd2..6530101cf 100644 --- a/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala +++ b/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala @@ -6,6 +6,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} class DataTypeSpecification extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("convert byte to DataType") { + DataType.fromByte(0) should be (None) DataType.fromByte(1) should be (Some(DataType.PublicKey)) DataType.fromByte(2) should be (Some(DataType.Address)) DataType.fromByte(3) should be (Some(DataType.Amount)) @@ -17,9 +18,10 @@ class DataTypeSpecification extends PropSpec with PropertyChecks with GeneratorD DataType.fromByte(9) should be (Some(DataType.Timestamp)) DataType.fromByte(10) should be (Some(DataType.Boolean)) DataType.fromByte(11) should be (Some(DataType.ShortBytes)) - DataType.fromByte(0) should be (None) DataType.fromByte(12) should be (Some(DataType.Balance)) DataType.fromByte(13) should be (Some(DataType.OpcBlock)) + DataType.fromByte(14) should be (Some(DataType.BigInteger)) + DataType.fromByte(15) should be (None) } property("convert DataType to byte") { @@ -34,5 +36,8 @@ class DataTypeSpecification extends PropSpec with PropertyChecks with GeneratorD DataType.Timestamp.id should be (9) DataType.Boolean.id should be (10) DataType.ShortBytes.id should be (11) + DataType.Balance.id should be (12) + DataType.OpcBlock.id should be (13) + DataType.BigInteger.id should be (14) } } From 8ffb2775664c71120011fe712f3fa0b885e010a6 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 24 Sep 2020 13:03:10 +0800 Subject: [PATCH 065/391] add some data entry tests --- .../contract/DataEntrySpecification.scala | 108 +++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/DataEntrySpecification.scala b/src/test/scala/vsys/blockchain/contract/DataEntrySpecification.scala index 3091847e2..cd98f1904 100644 --- a/src/test/scala/vsys/blockchain/contract/DataEntrySpecification.scala +++ b/src/test/scala/vsys/blockchain/contract/DataEntrySpecification.scala @@ -1,12 +1,13 @@ package vsys.blockchain.contract -import com.google.common.primitives.Longs +import com.google.common.primitives.{Ints, Longs} import vsys.blockchain.transaction.TransactionGen import org.scalacheck.Gen import org.scalatest.{Matchers, PropSpec} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import vsys.account.PublicKeyAccount import vsys.blockchain.transaction.ValidationError.InvalidDataEntry +import vsys.utils.serialization.Deser class DataEntrySpecification extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TransactionGen { @@ -19,9 +20,41 @@ class DataEntrySpecification extends PropSpec with PropertyChecks with Generator } yield DataEntry(data, DataType.Address) val validAmountEntryGen: Gen[DataEntry] = for { - data <- positiveLongGen.map(Longs.toByteArray(_)) + data <- positiveLongGen.map(Longs.toByteArray) } yield DataEntry(data, DataType.Amount) + val validInt32EntryGen: Gen[DataEntry] = for { + data <- positiveIntGen.map(Ints.toByteArray) + } yield DataEntry(data, DataType.Int32) + + val validShortTextEntryGen: Gen[DataEntry] = for { + data <- attachmentGen.map(Deser.serializeArray) + } yield DataEntry(data, DataType.ShortText) + + val validContractAccountEntryGen: Gen[DataEntry] = for { + data <- contractAccountGen.map(_.bytes.arr) + } yield DataEntry(data, DataType.ContractAccount) + + val validTimestampEntryGen: Gen[DataEntry] = for { + data <- timestampGen.map(Longs.toByteArray) + } yield DataEntry(data, DataType.Timestamp) + + val validBooleanEntryGen: Gen[DataEntry] = for { + data <- byteArrayGen(1).map(_.deep == Array(1.toByte).deep).map(if(_) 1 else 0).map(_.toByte).map(Array(_)) + } yield DataEntry(data, DataType.Boolean) + + val validShortBytesEntryGen: Gen[DataEntry] = for { + data <- attachmentGen.map(Deser.serializeArray) + } yield DataEntry(data, DataType.ShortBytes) + + val validOpcBlockEntryGen: Gen[DataEntry] = for { + data <- attachmentGen.map(Deser.serializeArray) + } yield DataEntry(data, DataType.OpcBlock) + + val validBigIntegerEntryGen: Gen[DataEntry] = for { + data <- attachmentGen.map(Deser.serializeArray) + } yield DataEntry(data, DataType.BigInteger) + property("convert entry to bytes and convert back") { forAll(validPublicKeyEntryGen) { pk: DataEntry => val recovered = DataEntry.fromBytes(pk.bytes).right.get @@ -40,19 +73,88 @@ class DataEntrySpecification extends PropSpec with PropertyChecks with Generator assertEys(recovered, pk) } + + forAll(validInt32EntryGen) { pk: DataEntry => + val recovered = DataEntry.fromBytes(pk.bytes).right.get + + assertEys(recovered, pk) + } + + forAll(validShortTextEntryGen) { pk: DataEntry => + val recovered = DataEntry.fromBytes(pk.bytes).right.get + + assertEys(recovered, pk) + } + + forAll(validContractAccountEntryGen) { pk: DataEntry => + val recovered = DataEntry.fromBytes(pk.bytes).right.get + + assertEys(recovered, pk) + } + + forAll(validTimestampEntryGen) { pk: DataEntry => + val recovered = DataEntry.fromBytes(pk.bytes).right.get + + assertEys(recovered, pk) + } + + forAll(validBooleanEntryGen) { pk: DataEntry => + val recovered = DataEntry.fromBytes(pk.bytes).right.get + + assertEys(recovered, pk) + } + + forAll(validShortBytesEntryGen) { pk: DataEntry => + val recovered = DataEntry.fromBytes(pk.bytes).right.get + + assertEys(recovered, pk) + } + + forAll(validOpcBlockEntryGen) { pk: DataEntry => + val recovered = DataEntry.fromBytes(pk.bytes).right.get + + assertEys(recovered, pk) + } + + forAll(validBigIntegerEntryGen) { pk: DataEntry => + val recovered = DataEntry.fromBytes(pk.bytes).right.get + + assertEys(recovered, pk) + } + } - property("report invalid data type") { + property("report invalid and valid data type") { val byteArray1 = Array[Byte](0, 118, 97, 108, 117, 101, 49) val byteArray2 = Array[Byte](4, 118, 97, 108, 117, 101, 49) val byteArray3 = Array.fill[Byte](1 + 32)(1) val byteArray4 = Array.fill[Byte](1 + 26)(2) val byteArray5 = Array.fill[Byte](1 + 8)(3) + val byteArray6 = Array.fill[Byte](1 + 4)(4) + val byteArray7 = Array[Byte](5, 0, 0) + val byteArray8 = Array.fill[Byte](1 + 26)(6) + val byteArray9 = Array.fill[Byte](1 + 26)(7) + val byteArray10 = Array.fill[Byte](1 + 8)(9) + val byteArray11 = Array[Byte](10, 1) + val byteArray12 = Array[Byte](11, 0, 0) + val byteArray13 = Array[Byte](12, 118, 97, 108, 117, 101, 49) + val byteArray14 = Array[Byte](13, 0, 0) + val byteArray15 = Array[Byte](14, 0, 0) DataEntry.fromBytes(byteArray1) should be (Left(InvalidDataEntry)) DataEntry.fromBytes(byteArray2) should be (Left(InvalidDataEntry)) DataEntry.fromBytes(byteArray3).map(_.dataType) should be (Right(DataType.PublicKey)) DataEntry.fromBytes(byteArray4).map(_.dataType) should be (Left(InvalidDataEntry)) DataEntry.fromBytes(byteArray5).map(_.dataType) should be (Right(DataType.Amount)) + DataEntry.fromBytes(byteArray6).map(_.dataType) should be (Right(DataType.Int32)) + DataEntry.fromBytes(byteArray7).map(_.dataType) should be (Right(DataType.ShortText)) + DataEntry.fromBytes(byteArray8).map(_.dataType) should be (Left(InvalidDataEntry)) + DataEntry.fromBytes(byteArray9).map(_.dataType) should be (Left(InvalidDataEntry)) + DataEntry.fromBytes(byteArray10).map(_.dataType) should be (Right(DataType.Timestamp)) + DataEntry.fromBytes(byteArray11).map(_.dataType) should be (Right(DataType.Boolean)) + DataEntry.fromBytes(byteArray12).map(_.dataType) should be (Right(DataType.ShortBytes)) + DataEntry.fromBytes(byteArray13).map(_.dataType) should be (Left(InvalidDataEntry)) + DataEntry.fromBytes(byteArray14).map(_.dataType) should be (Right(DataType.OpcBlock)) + DataEntry.fromBytes(byteArray15).map(_.dataType) should be (Right(DataType.BigInteger)) } private def assertEys(first: DataEntry, second: DataEntry): Unit = { From 53f812140acd7152ca4cb03bcd2c99db7196fac4 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 24 Sep 2020 17:13:51 +0800 Subject: [PATCH 066/391] temporary modify --- src/main/scala/vsys/blockchain/contract/DataEntry.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index e1e355b95..5ad71a9a5 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -34,7 +34,7 @@ object DataEntry { else doCreate(DataType.arrayShortLengthToByteArray(data) ++ data, dataType) // length unfixed data array should start with 2 bytes which indicates length of content of data - private def doCreate(data: Array[Byte], dataType: DataType.DataTypeVal[_]): Either[ValidationError, DataEntry] = + def doCreate(data: Array[Byte], dataType: DataType.DataTypeVal[_]): Either[ValidationError, DataEntry] = if (dataType.validator(data)) Right(DataEntry(data, dataType)) else Left(InvalidDataEntry) def fromBytes(bytes: Array[Byte]): Either[ValidationError, DataEntry] = { From 7b5278016cec9d126be2468fb156425801d3bf63 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 24 Sep 2020 17:14:38 +0800 Subject: [PATCH 067/391] fix bug --- .../scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index f10034a21..2a7849588 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -19,7 +19,7 @@ object BasicOpcDiff extends OpcDiffer { private def appendRes[T] (p: Byte, res: T, dt: DataType.DataTypeVal[T], ds: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = for { _ <- if(dt.validator(dt.serializer(res))) Right(()) else Left(ValidationError.OverflowError) - zDataEntry <- DataEntry.create(dt.serializer(res), dt) + zDataEntry <- DataEntry.doCreate(dt.serializer(res), dt) } yield ds.patch(p, Seq(zDataEntry), 1) def operation(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], From 4754b5050827dbf3b3f8baafe420d9644eb84c46 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 24 Sep 2020 17:15:15 +0800 Subject: [PATCH 068/391] add unit tests for bigint --- .../state/opcdiffs/BasicOpcDiffTest.scala | 97 ++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala index ada5daac8..b1f26215f 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -1,13 +1,12 @@ package vsys.blockchain.state.opcdiffs -import com.google.common.primitives.{Ints, Longs} +import com.google.common.primitives.{Ints, Longs, Shorts} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.DataType.MaxShortBytesLength import vsys.blockchain.transaction.ValidationError -import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractLocalVariableIndexOutOfRange, - ContractUnsupportedOPC, InvalidDataEntry} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractLocalVariableIndexOutOfRange, ContractUnsupportedOPC, InvalidDataEntry} import scala.util.{Left, Right} @@ -35,6 +34,20 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.ShortText), Seq.empty, 0, BasicOpcDiff.add) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 0, BasicOpcDiff.add) should be (Right(Seq(DataEntry( + Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 1, BasicOpcDiff.add) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0, BasicOpcDiff.add) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), @@ -56,6 +69,20 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.ShortText), Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 0, BasicOpcDiff.minus) should be (Right(Seq(DataEntry( + Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 1, BasicOpcDiff.minus) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), @@ -77,6 +104,24 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.ShortText), Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), + Seq.empty, 0, BasicOpcDiff.multiply) should be (Right(Seq(DataEntry( + Shorts.toByteArray(BigInt(4).toByteArray.length.toShort) ++ BigInt(4).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray((BigInt(1) << 255*8).toByteArray.length.toShort) ++ (BigInt(1) << 255*8).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray((BigInt(1) << 255*8).toByteArray.length.toShort) ++ (BigInt(1) << 255*8).toByteArray, DataType.BigInteger), + Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 1, BasicOpcDiff.multiply) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), @@ -98,6 +143,24 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.ShortText), Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), + Seq.empty, 0, BasicOpcDiff.divide) should be (Right(Seq(DataEntry( + Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 1, BasicOpcDiff.divide) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), @@ -115,6 +178,20 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.ShortText), Seq.empty, 0, BasicOpcDiff.minimum) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), + Seq.empty, 0, BasicOpcDiff.minimum) should be (Right(Seq(DataEntry( + Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 1, BasicOpcDiff.minimum) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0, BasicOpcDiff.minimum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.operation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), @@ -132,6 +209,20 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.ShortText), Seq.empty, 0, BasicOpcDiff.maximum) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), + Seq.empty, 0, BasicOpcDiff.maximum) should be (Right(Seq(DataEntry( + Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + Seq.empty, 1, BasicOpcDiff.maximum) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.operation( + DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), + DataEntry(Longs.toByteArray(1), DataType.Timestamp), + Seq.empty, 0, BasicOpcDiff.maximum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.concat( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), From ad413712ff9f82de40b1fbf679b7c74c338f07e7 Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 25 Sep 2020 15:01:38 +0800 Subject: [PATCH 069/391] new datatype datatype --- .../scala/vsys/blockchain/contract/DataType.scala | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index 5af712a6a..33b212b74 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -19,7 +19,7 @@ object DataType extends Enumeration { sealed case class DataTypeVal[T](dataType: Int, lenFixed: Boolean, maxLen: Int, deserializer: Array[Byte] => T, - serializer: T => Array[Byte], + serializer: T => Array[Byte], // WITHOUT length prefix jsonifier: T => JsValue, private val extValidator: Array[Byte] => Boolean) extends Val(dataType) { @@ -33,6 +33,15 @@ object DataType extends Enumeration { && extValidator(data)) } + + val DataTypeObj = DataTypeVal[DataTypeVal[_]](0, + lenFixed = true, + maxLen = 1, + deserializer = x => fromByte(x(1)).get, + serializer = v => Array(v.id.toByte), + jsonifier = v => Json.toJson(v.toString), + extValidator = x => fromByte(x(1)).nonEmpty) + val PublicKey = DataTypeVal[PublicKeyAccount](1, lenFixed = true, maxLen = KeyLength, @@ -154,7 +163,7 @@ object DataType extends Enumeration { jsonifier = i => Json.toJson(i.toString), extValidator = _ => true) - def fromByte(b: Byte): Option[DataType.DataTypeVal[_]] = Try(DataType(b).asInstanceOf[DataTypeVal[_]]).toOption + def fromByte(b: Byte): Option[DataTypeVal[_]] = Try(DataType(b).asInstanceOf[DataTypeVal[_]]).toOption def check(a: Byte, b: Byte): Boolean = { if (a == b) true From ef9b03301165a34abd34c6d735a66d05da211b3e Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 25 Sep 2020 15:02:12 +0800 Subject: [PATCH 070/391] convertions between dataTypes --- .../state/opcdiffs/BasicOpcDiff.scala | 153 ++++++++++-------- 1 file changed, 86 insertions(+), 67 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index f10034a21..bc893426c 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -5,53 +5,47 @@ import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} import vsys.blockchain.contract.DataType._ -import scala.util.{Left, Right, Try, Success, Failure} +import scala.language.implicitConversions +import scala.util.{Left, Try} object BasicOpcDiff extends OpcDiffer { - case class BiOperator(int: (Int, Int) => Try[Int], long: (Long, Long) => Try[Long], bigInt: (BigInt, BigInt) => Try[BigInt]) - val add = BiOperator((x, y) => Try(Math.addExact(x, y)), (x, y) => Try(Math.addExact(x, y)), (x, y) => Success(x + y)) - val minus = BiOperator((x, y) => Try(Math.subtractExact(x, y)), (x, y) => Try(Math.subtractExact(x, y)), (x, y) => Success(x - y)) - val multiply = BiOperator((x, y) => Try(Math.multiplyExact(x, y)), (x, y) => Try(Math.multiplyExact(x, y)), (x, y) => Success(x * y)) - val divide = BiOperator((x, y) => Try(Math.floorDiv(x, y)), (x, y) => Try(Math.floorDiv(x, y)), (x, y) => Try(x / y)) - val minimum = BiOperator((x, y) => Try(Math.min(x, y)), (x, y) => Try(Math.min(x, y)), (x, y) => Success(x.min(y))) - val maximum = BiOperator((x, y) => Try(Math.max(x, y)), (x, y) => Try(Math.max(x, y)), (x, y) => Success(x.max(y))) - - private def appendRes[T] (p: Byte, res: T, dt: DataType.DataTypeVal[T], ds: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = for { - _ <- if(dt.validator(dt.serializer(res))) Right(()) else Left(ValidationError.OverflowError) - zDataEntry <- DataEntry.create(dt.serializer(res), dt) - } yield ds.patch(p, Seq(zDataEntry), 1) - - def operation(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte, operator: BiOperator): Either[ValidationError, Seq[DataEntry]] = - if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) - else if (x.dataType == y.dataType) x.dataType match { - case Int32 => operator.int(Int32.deserializer(x.data), Int32.deserializer(y.data)) match { - case Failure(_) => Left(ValidationError.OverflowError) - case Success(res: Int) => appendRes[Int](pointer, res, Int32, dataStack) - } - case Amount => operator.long(Amount.deserializer(x.data), Amount.deserializer(y.data)) match { - case Failure(_) => Left(ValidationError.OverflowError) - case Success(res: Long) => appendRes[Long](pointer, res, Amount, dataStack) - } - case Timestamp => operator.long(Timestamp.deserializer(x.data), Timestamp.deserializer(y.data)) match { - case Failure(_) => Left(ValidationError.OverflowError) - case Success(res: Long) => appendRes[Long](pointer, res, Timestamp, dataStack) - } - case BigInteger => operator.bigInt(BigInteger.deserializer(x.data), BigInteger.deserializer(y.data)) match { - case Failure(_) => Left(ValidationError.OverflowError) - case Success(res: BigInt) => appendRes[BigInt](pointer, res, BigInteger, dataStack) - } + case class BiOperator(int$1: (Int, Int) => Int, long$1: (Long, Long) => Long, bigInt$1: (BigInt, BigInt) => BigInt) { + val int: (Int, Int) => Try[Int] = (x, y) => Try(int$1(x, y)) + val long: (Long, Long) => Try[Long] = (x, y) => Try(long$1(x, y)) + val bigInt: (BigInt, BigInt) => Try[BigInt] = (x, y) => Try(bigInt$1(x, y)) + } + val add = BiOperator(Math.addExact, Math.addExact, _ + _) + val minus = BiOperator(Math.subtractExact, Math.subtractExact, _ - _) + val multiply = BiOperator(Math.multiplyExact, Math.multiplyExact, _ * _) + val divide = BiOperator(Math.floorDiv, Math.floorDiv, _ / _) + val minimum = BiOperator(Math.min, Math.min, (x, y) => x.min(y)) + val maximum = BiOperator(Math.max, Math.max, (x, y) => x.max(y)) + + private implicit def dataEntry2Int(x: DataEntry): Int = Int32.deserializer(x.data) + + private implicit def dataEntry2Long(x: DataEntry): Long = Amount.deserializer(x.data) + + private implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) + + private implicit def try2Either(t: Try[Either[ValidationError, DataEntry]]): Either[ValidationError, DataEntry] = + t.recover({ case _ => Left(OverflowError) }).get + + def operation(x: DataEntry, y: DataEntry, operator: BiOperator): Either[ValidationError, DataEntry] = + if (x.dataType == y.dataType) x.dataType match { + case Int32 => operator.int(x, y).map(formatRes[Int](_, Int32)) + case Amount => operator.long(x, y).map(formatRes[Long](_, Amount)) + case Timestamp => operator.long(x, y).map(formatRes[Long](_, Timestamp)) + case BigInteger => operator.bigInt(x, y).map(formatRes[BigInt](_, BigInteger)) case _ => Left(ContractUnsupportedOPC) } else Left(ContractDataTypeMismatch) - def sqrt(x: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = - if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) - else x.dataType match { + def sqrt(x: DataEntry): Either[ValidationError, DataEntry] = + x.dataType match { case BigInteger => { val value = BigInteger.deserializer(x.data) if (value < 0) Left(ValidationError.OverflowError) - else appendRes[BigInt](pointer, sqrtBigInt(value), BigInteger, dataStack) + else formatRes[BigInt](sqrtBigInt(value), BigInteger) } case _ => Left(ContractUnsupportedOPC) } @@ -61,52 +55,77 @@ object BasicOpcDiff extends OpcDiffer { if (y > 3) Stream.iterate((y, (y >> 1) + 1)){ case (z, x) => (x, (y / x + x) >> 1) }.dropWhile{ case(z, x) => x < z }.head._1 else if (y > 0) 1 else 0 } - def concat(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - for { - res <- DataEntry.create(x.data ++ y.data, DataType.ShortBytes) - } yield dataStack.patch(pointer, Seq(res), 1) - } - } - def constantGet(constant: Array[Byte], dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - DataEntry.fromBytes(constant) match { - case Right(v) => Right(dataStack.patch(pointer, Seq(v), 1)) - case Left(e) => Left(e) + def convertion(x: DataEntry, t: DataEntry): Either[ValidationError, DataEntry] = + t.dataType match { + case DataTypeObj => x.dataType match { + case Int32 | Amount | Timestamp | BigInteger => { + val to: DataTypeVal[_] = DataTypeObj.deserializer(t.data) + to match { + case Int32 => formatResB[Int] (x.data, Int32) + case Amount => formatResB[Long] (x.data, Amount) + case Timestamp => formatResB[Long] (x.data, Timestamp) + case BigInteger => formatResB[BigInt](x.data, BigInteger) + case _ => Left(ContractUnsupportedOPC) + } + } + case _ => Left(ContractUnsupportedOPC) } + case _ => Left(ContractInvalidOPCData) } - } + + + def concat(x: DataEntry, y: DataEntry): Either[ValidationError, DataEntry] = + DataEntry.create(x.data ++ y.data, DataType.ShortBytes) + + def constantGet(constant: Array[Byte]): Either[ValidationError, DataEntry] = + DataEntry.fromBytes(constant) object BasicType extends Enumeration { sealed case class basicTypeVal( basicType: Int, len: Int, - differ: (Array[Byte], Seq[DataEntry]) => Either[ValidationError, Seq[DataEntry]]) + indexes: Seq[Int], + op: (Array[Byte], Seq[DataEntry]) => Either[ValidationError, DataEntry]) extends Val(basicType) { def *(n: Int): Int = n * basicType } - val Add = basicTypeVal(1, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), add)) - val Minus = basicTypeVal(2, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), minus)) - val Multiply = basicTypeVal(3, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), multiply)) - val Divide = basicTypeVal(4, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), divide)) - val Minimum = basicTypeVal(5, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), minimum)) - val Maximum = basicTypeVal(6, 4, (b, d) => operation(d(b(1)), d(b(2)), d, b(3), maximum)) - val Concat = basicTypeVal(7, 4, (b, d) => concat(d(b(1)), d(b(2)), d, b(3))) - val ConstantGet = basicTypeVal(8, 2, (b, d) => constantGet(b.slice(1, b.length-1), d, b(b.length-1))) - val SqrtBigInt = basicTypeVal(9, 3, (b, d) => sqrt(d(b(1)), d, b(2))) + val Add = basicTypeVal(1, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), add)) + val Minus = basicTypeVal(2, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), minus)) + val Multiply = basicTypeVal(3, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), multiply)) + val Divide = basicTypeVal(4, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), divide)) + val Minimum = basicTypeVal(5, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), minimum)) + val Maximum = basicTypeVal(6, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), maximum)) + val Concat = basicTypeVal(7, 4, Seq(1, 2), (b, d) => concat(d(b(1)), d(b(2)))) + val ConstantGet = basicTypeVal(8, 2, Seq(), (b, d) => constantGet(b.slice(1, b.length-1))) + val SqrtBigInt = basicTypeVal(9, 3, Seq(1), (b, d) => sqrt(d(b(1)))) + val Convert = basicTypeVal(10, 3, Seq(1, 2), (b, d) => convertion(d(b(1)), d(b(1)))) } + // res is call-by-name + private def updateStack(dataStack: Seq[DataEntry], pointer: Byte, + res: => Either[ValidationError, DataEntry]): Either[ValidationError, Seq[DataEntry]] = + if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) + else res.map(r => dataStack.patch(pointer, Seq(r), 1)) + + private def formatRes[T] (res: T, dt: DataTypeVal[T]): Either[ValidationError, DataEntry] = + formatResB[T](dt.serializer(res), dt) + + private def formatResB[T] (res: Array[Byte], dt: DataTypeVal[T]): Either[ValidationError, DataEntry] = + DataEntry.create(res, dt).left.map(_ => ValidationError.OverflowError) + + def differ(bytes: Array[Byte], data: Seq[DataEntry], t: BasicType.basicTypeVal) = updateStack(data, bytes.last, t.op(bytes, data)) + override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(BasicType(f)).toOption) match { - case Some(t: BasicType.basicTypeVal) if checkBytesLength(bytes, t) => t.differ(bytes, data) + case Some(t: BasicType.basicTypeVal) if checkBytesLength(bytes, t) && checkIndex(bytes, data, t) => differ(bytes, data, t) case _ => Left(ContractInvalidOPCData) } private def checkBytesLength(bytes: Array[Byte], t: BasicType.basicTypeVal): Boolean = { - (t.basicType == 8 && bytes.length > t.len) || (bytes.length == t.len) + (t == BasicType.ConstantGet && bytes.length > t.len) || (bytes.length == t.len) } + + private def checkIndex(bytes: Array[Byte], dataStack: Seq[DataEntry], t: BasicType.basicTypeVal): Boolean = + t.indexes.map(bytes(_)).filterNot(idx => idx < dataStack.length && idx >= 0).isEmpty + } From 67649eae2099b7a82dbe5c98bd7c2e5315d15317 Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 25 Sep 2020 15:59:52 +0800 Subject: [PATCH 071/391] add boolean operators --- .../vsys/blockchain/contract/DataType.scala | 12 +-- .../state/opcdiffs/BasicOpcDiff.scala | 74 +++++++++++++------ 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index 33b212b74..3a6068482 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -18,8 +18,8 @@ object DataType extends Enumeration { val MaxBigIntLength = 255 // less than 1024 bits sealed case class DataTypeVal[T](dataType: Int, lenFixed: Boolean, maxLen: Int, - deserializer: Array[Byte] => T, - serializer: T => Array[Byte], // WITHOUT length prefix + deserializer: Array[Byte] => T, // take bytes WITH length prefix if length not fixed + serializer: T => Array[Byte], // returns WITHOUT length prefix jsonifier: T => JsValue, private val extValidator: Array[Byte] => Boolean) extends Val(dataType) { @@ -78,7 +78,7 @@ object DataType extends Enumeration { lenFixed = false, maxLen = MaxShortTextLength, deserializer = b => new String(b.drop(2)), - serializer = s => arrayShortLengthToByteArray(s.getBytes) ++ s.getBytes, + serializer = s => s.getBytes, jsonifier = Json.toJson(_), extValidator = _ => true) @@ -135,7 +135,7 @@ object DataType extends Enumeration { lenFixed = false, maxLen = MaxShortBytesLength, deserializer = b => b.drop(2), - serializer = b => arrayShortLengthToByteArray(b) ++ b, + serializer = b => b, jsonifier = b => Json.toJson(Base58.encode(b)), extValidator = _ => true) @@ -151,7 +151,7 @@ object DataType extends Enumeration { lenFixed = false, maxLen = MaxOpcBlockLength, deserializer = b => b.drop(2), - serializer = b => arrayShortLengthToByteArray(b) ++ b, + serializer = b => b, jsonifier = b => Json.toJson(Base58.encode(b)), extValidator = _ => true) @@ -159,7 +159,7 @@ object DataType extends Enumeration { lenFixed = false, maxLen = MaxBigIntLength, deserializer = b => BigInt(b.drop(2)), - serializer = i => arrayShortLengthToByteArray(i.toByteArray) ++ i.toByteArray, + serializer = i => i.toByteArray, jsonifier = i => Json.toJson(i.toString), extValidator = _ => true) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index bc893426c..fc13cf361 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -10,28 +10,47 @@ import scala.util.{Left, Try} object BasicOpcDiff extends OpcDiffer { - case class BiOperator(int$1: (Int, Int) => Int, long$1: (Long, Long) => Long, bigInt$1: (BigInt, BigInt) => BigInt) { + case class NumBiOperator(int$1: (Int, Int) => Int, long$1: (Long, Long) => Long, bigInt$1: (BigInt, BigInt) => BigInt) { val int: (Int, Int) => Try[Int] = (x, y) => Try(int$1(x, y)) val long: (Long, Long) => Try[Long] = (x, y) => Try(long$1(x, y)) val bigInt: (BigInt, BigInt) => Try[BigInt] = (x, y) => Try(bigInt$1(x, y)) } - val add = BiOperator(Math.addExact, Math.addExact, _ + _) - val minus = BiOperator(Math.subtractExact, Math.subtractExact, _ - _) - val multiply = BiOperator(Math.multiplyExact, Math.multiplyExact, _ * _) - val divide = BiOperator(Math.floorDiv, Math.floorDiv, _ / _) - val minimum = BiOperator(Math.min, Math.min, (x, y) => x.min(y)) - val maximum = BiOperator(Math.max, Math.max, (x, y) => x.max(y)) + val add = NumBiOperator(Math.addExact, Math.addExact, _ + _) + val minus = NumBiOperator(Math.subtractExact, Math.subtractExact, _ - _) + val multiply = NumBiOperator(Math.multiplyExact, Math.multiplyExact, _ * _) + val divide = NumBiOperator(Math.floorDiv, Math.floorDiv, _ / _) + val minimum = NumBiOperator(Math.min, Math.min, (x, y) => x.min(y)) + val maximum = NumBiOperator(Math.max, Math.max, (x, y) => x.max(y)) - private implicit def dataEntry2Int(x: DataEntry): Int = Int32.deserializer(x.data) + // babylonian method + def sqrtBigInt(y: BigInt): BigInt = { + if (y > 3) Stream.iterate((y, (y >> 1) + 1)){ case (z, x) => (x, (y / x + x) >> 1) }.dropWhile{ case(z, x) => x < z }.head._1 + else if (y > 0) 1 else 0 + } - private implicit def dataEntry2Long(x: DataEntry): Long = Amount.deserializer(x.data) + // not converting byte to boolean + case class BoolByteBiOperator(val op: (Byte, Byte) => Byte) - private implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) + val bAnd = BoolByteBiOperator(_ & _) + val bOr = BoolByteBiOperator(_ | _) + val bXor = BoolByteBiOperator(_ ^ _) + + val bNot: Byte => Byte = x => ~x & 1 + + implicit def int2Byte(x:Int): Byte = x.toByte + + implicit def dataEntry2Int(x: DataEntry): Int = Int32.deserializer(x.data) + + implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) + + implicit def boolDataEntry2Byte(x: DataEntry): Byte = x.data(0) + + private implicit def dataEntry2Long(x: DataEntry): Long = Amount.deserializer(x.data) private implicit def try2Either(t: Try[Either[ValidationError, DataEntry]]): Either[ValidationError, DataEntry] = t.recover({ case _ => Left(OverflowError) }).get - def operation(x: DataEntry, y: DataEntry, operator: BiOperator): Either[ValidationError, DataEntry] = + def numBiOperation(x: DataEntry, y: DataEntry, operator: NumBiOperator): Either[ValidationError, DataEntry] = if (x.dataType == y.dataType) x.dataType match { case Int32 => operator.int(x, y).map(formatRes[Int](_, Int32)) case Amount => operator.long(x, y).map(formatRes[Long](_, Amount)) @@ -50,11 +69,15 @@ object BasicOpcDiff extends OpcDiffer { case _ => Left(ContractUnsupportedOPC) } - // babylonian method - def sqrtBigInt(y: BigInt): BigInt = { - if (y > 3) Stream.iterate((y, (y >> 1) + 1)){ case (z, x) => (x, (y / x + x) >> 1) }.dropWhile{ case(z, x) => x < z }.head._1 - else if (y > 0) 1 else 0 - } + def boolBiOperation(x: DataEntry, y: DataEntry, operator: BoolByteBiOperator): Either[ValidationError, DataEntry] = + if (x.dataType == y.dataType && x.dataType == Boolean) formatResB[Boolean](Array(operator.op(x, y)), Boolean) + else Left(ContractInvalidOPCData) + + def not(x: DataEntry): Either[ValidationError, DataEntry] = + x.dataType match { + case Boolean => formatResB[Boolean](Array(bNot(x)), Boolean) + case _ => Left(ContractUnsupportedOPC) + } def convertion(x: DataEntry, t: DataEntry): Either[ValidationError, DataEntry] = t.dataType match { @@ -74,7 +97,6 @@ object BasicOpcDiff extends OpcDiffer { case _ => Left(ContractInvalidOPCData) } - def concat(x: DataEntry, y: DataEntry): Either[ValidationError, DataEntry] = DataEntry.create(x.data ++ y.data, DataType.ShortBytes) @@ -89,16 +111,20 @@ object BasicOpcDiff extends OpcDiffer { op: (Array[Byte], Seq[DataEntry]) => Either[ValidationError, DataEntry]) extends Val(basicType) { def *(n: Int): Int = n * basicType } - val Add = basicTypeVal(1, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), add)) - val Minus = basicTypeVal(2, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), minus)) - val Multiply = basicTypeVal(3, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), multiply)) - val Divide = basicTypeVal(4, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), divide)) - val Minimum = basicTypeVal(5, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), minimum)) - val Maximum = basicTypeVal(6, 4, Seq(1, 2), (b, d) => operation(d(b(1)), d(b(2)), maximum)) + val Add = basicTypeVal(1, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), add)) + val Minus = basicTypeVal(2, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), minus)) + val Multiply = basicTypeVal(3, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), multiply)) + val Divide = basicTypeVal(4, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), divide)) + val Minimum = basicTypeVal(5, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), minimum)) + val Maximum = basicTypeVal(6, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), maximum)) val Concat = basicTypeVal(7, 4, Seq(1, 2), (b, d) => concat(d(b(1)), d(b(2)))) val ConstantGet = basicTypeVal(8, 2, Seq(), (b, d) => constantGet(b.slice(1, b.length-1))) val SqrtBigInt = basicTypeVal(9, 3, Seq(1), (b, d) => sqrt(d(b(1)))) - val Convert = basicTypeVal(10, 3, Seq(1, 2), (b, d) => convertion(d(b(1)), d(b(1)))) + val Convert = basicTypeVal(10, 4, Seq(1, 2), (b, d) => convertion(d(b(1)), d(b(2)))) + val And = basicTypeVal(11, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bAnd)) + val Or = basicTypeVal(12, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bOr)) + val Xor = basicTypeVal(13, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bXor)) + val Not = basicTypeVal(14, 3, Seq(1), (b, d) => not(d(b(1)))) } // res is call-by-name From ca32776aa70fc3b24fa8dfced280c385c41de414 Mon Sep 17 00:00:00 2001 From: Icermli Date: Fri, 25 Sep 2020 16:33:58 +0800 Subject: [PATCH 072/391] add sqrt func test --- .../state/opcdiffs/BasicOpcDiffTest.scala | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala index b1f26215f..62744531b 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -6,7 +6,8 @@ import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.DataType.MaxShortBytesLength import vsys.blockchain.transaction.ValidationError -import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractLocalVariableIndexOutOfRange, ContractUnsupportedOPC, InvalidDataEntry} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractLocalVariableIndexOutOfRange, + ContractUnsupportedOPC, InvalidDataEntry} import scala.util.{Left, Right} @@ -223,6 +224,29 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.Timestamp), Seq.empty, 0, BasicOpcDiff.maximum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.sqrt( + DataEntry(Longs.toByteArray(1), DataType.Amount), + Seq.empty, + 0) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.sqrt( + DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), + Seq.empty, + 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + BasicOpcDiff.sqrt( + DataEntry(Shorts.toByteArray(BigInt(-1).toByteArray.length.toShort) ++ BigInt(-1).toByteArray, DataType.BigInteger), + Seq.empty, + 0) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.sqrt( + DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), + Seq.empty, + 0) should be (Right(Seq(DataEntry( + Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.sqrt( + DataEntry(Shorts.toByteArray(BigInt(4).toByteArray.length.toShort) ++ BigInt(4).toByteArray, DataType.BigInteger), + Seq.empty, + 0) should be (Right(Seq(DataEntry( + Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.concat( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), From 12724d235f020f31e84cd66eccc98e690e5561b1 Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 25 Sep 2020 16:58:45 +0800 Subject: [PATCH 073/391] add comparators --- .../state/opcdiffs/BasicOpcDiff.scala | 56 +++++++------------ .../state/opcdiffs/CompareOpcDiff.scala | 50 ++++++++++------- .../blockchain/state/opcdiffs/OpcDiffer.scala | 23 +++++++- 3 files changed, 71 insertions(+), 58 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index fc13cf361..52a85f18e 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -4,6 +4,7 @@ import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} import vsys.blockchain.contract.DataType._ +import vsys.blockchain.state.opcdiffs.OpcDiffer._ import scala.language.implicitConversions import scala.util.{Left, Try} @@ -37,16 +38,6 @@ object BasicOpcDiff extends OpcDiffer { val bNot: Byte => Byte = x => ~x & 1 - implicit def int2Byte(x:Int): Byte = x.toByte - - implicit def dataEntry2Int(x: DataEntry): Int = Int32.deserializer(x.data) - - implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) - - implicit def boolDataEntry2Byte(x: DataEntry): Byte = x.data(0) - - private implicit def dataEntry2Long(x: DataEntry): Long = Amount.deserializer(x.data) - private implicit def try2Either(t: Try[Either[ValidationError, DataEntry]]): Either[ValidationError, DataEntry] = t.recover({ case _ => Left(OverflowError) }).get @@ -104,54 +95,45 @@ object BasicOpcDiff extends OpcDiffer { DataEntry.fromBytes(constant) object BasicType extends Enumeration { - sealed case class basicTypeVal( + sealed case class BasicTypeVal( basicType: Int, len: Int, indexes: Seq[Int], op: (Array[Byte], Seq[DataEntry]) => Either[ValidationError, DataEntry]) extends Val(basicType) { def *(n: Int): Int = n * basicType } - val Add = basicTypeVal(1, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), add)) - val Minus = basicTypeVal(2, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), minus)) - val Multiply = basicTypeVal(3, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), multiply)) - val Divide = basicTypeVal(4, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), divide)) - val Minimum = basicTypeVal(5, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), minimum)) - val Maximum = basicTypeVal(6, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), maximum)) - val Concat = basicTypeVal(7, 4, Seq(1, 2), (b, d) => concat(d(b(1)), d(b(2)))) - val ConstantGet = basicTypeVal(8, 2, Seq(), (b, d) => constantGet(b.slice(1, b.length-1))) - val SqrtBigInt = basicTypeVal(9, 3, Seq(1), (b, d) => sqrt(d(b(1)))) - val Convert = basicTypeVal(10, 4, Seq(1, 2), (b, d) => convertion(d(b(1)), d(b(2)))) - val And = basicTypeVal(11, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bAnd)) - val Or = basicTypeVal(12, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bOr)) - val Xor = basicTypeVal(13, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bXor)) - val Not = basicTypeVal(14, 3, Seq(1), (b, d) => not(d(b(1)))) + val Add = BasicTypeVal(1, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), add)) + val Minus = BasicTypeVal(2, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), minus)) + val Multiply = BasicTypeVal(3, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), multiply)) + val Divide = BasicTypeVal(4, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), divide)) + val Minimum = BasicTypeVal(5, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), minimum)) + val Maximum = BasicTypeVal(6, 4, Seq(1, 2), (b, d) => numBiOperation(d(b(1)), d(b(2)), maximum)) + val Concat = BasicTypeVal(7, 4, Seq(1, 2), (b, d) => concat(d(b(1)), d(b(2)))) + val ConstantGet = BasicTypeVal(8, 2, Seq(), (b, d) => constantGet(b.slice(1, b.length-1))) + val SqrtBigInt = BasicTypeVal(9, 3, Seq(1), (b, d) => sqrt(d(b(1)))) + val Convert = BasicTypeVal(10, 4, Seq(1, 2), (b, d) => convertion(d(b(1)), d(b(2)))) + val And = BasicTypeVal(11, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bAnd)) + val Or = BasicTypeVal(12, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bOr)) + val Xor = BasicTypeVal(13, 4, Seq(1, 2), (b, d) => boolBiOperation(d(b(1)), d(b(2)), bXor)) + val Not = BasicTypeVal(14, 3, Seq(1), (b, d) => not(d(b(1)))) } - // res is call-by-name - private def updateStack(dataStack: Seq[DataEntry], pointer: Byte, - res: => Either[ValidationError, DataEntry]): Either[ValidationError, Seq[DataEntry]] = - if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) - else res.map(r => dataStack.patch(pointer, Seq(r), 1)) - private def formatRes[T] (res: T, dt: DataTypeVal[T]): Either[ValidationError, DataEntry] = formatResB[T](dt.serializer(res), dt) private def formatResB[T] (res: Array[Byte], dt: DataTypeVal[T]): Either[ValidationError, DataEntry] = DataEntry.create(res, dt).left.map(_ => ValidationError.OverflowError) - def differ(bytes: Array[Byte], data: Seq[DataEntry], t: BasicType.basicTypeVal) = updateStack(data, bytes.last, t.op(bytes, data)) + def differ(bytes: Array[Byte], data: Seq[DataEntry], t: BasicType.BasicTypeVal) = updateStack(data, bytes.last, t.op(bytes, data)) override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(BasicType(f)).toOption) match { - case Some(t: BasicType.basicTypeVal) if checkBytesLength(bytes, t) && checkIndex(bytes, data, t) => differ(bytes, data, t) + case Some(t: BasicType.BasicTypeVal) if checkBytesLength(bytes, t) && checkIndexes(bytes, data, t.indexes) => differ(bytes, data, t) case _ => Left(ContractInvalidOPCData) } - private def checkBytesLength(bytes: Array[Byte], t: BasicType.basicTypeVal): Boolean = { + private def checkBytesLength(bytes: Array[Byte], t: BasicType.BasicTypeVal): Boolean = { (t == BasicType.ConstantGet && bytes.length > t.len) || (bytes.length == t.len) } - private def checkIndex(bytes: Array[Byte], dataStack: Seq[DataEntry], t: BasicType.basicTypeVal): Boolean = - t.indexes.map(bytes(_)).filterNot(idx => idx < dataStack.length && idx >= 0).isEmpty - } diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala index fb137cb6d..a8c14e530 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala @@ -1,40 +1,50 @@ package vsys.blockchain.state.opcdiffs -import com.google.common.primitives.Longs import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} +import vsys.blockchain.contract.DataType._ +import vsys.blockchain.state.opcdiffs.OpcDiffer._ +import scala.language.implicitConversions import scala.util.{Left, Right, Try} object CompareOpcDiff extends OpcDiffer { - def geq(x: DataEntry, y: DataEntry, dataStack: Seq[DataEntry], - pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (x.dataType == y.dataType) { - val supportList = List(DataType.Amount, DataType.Timestamp) - supportList.find(a => a == x.dataType) match { - case Some(_) => { - val xValue = Longs.fromByteArray(x.data) - val yValue = Longs.fromByteArray(y.data) - if (xValue >= yValue) { - Right(dataStack.patch(pointer, Seq(DataEntry(Array(1.toByte), DataType.Boolean)), 1)) - } else { - Right(dataStack.patch(pointer, Seq(DataEntry(Array(0.toByte), DataType.Boolean)), 1)) - } - } - case None => Left(ContractUnsupportedOPC) - } + case class NumComparator(int: (Int, Int) => Boolean, long: (Long, Long) => Boolean, bigInt: (BigInt, BigInt) => Boolean) + + val ge = NumComparator(_ >= _, _ >= _, _ >= _) + val gt = NumComparator(_ > _, _ > _, _ > _) + val le = NumComparator(_ <= _, _ <= _, _ <= _) + val lt = NumComparator(_ < _, _ < _, _ < _) + val _eq = NumComparator(_ == _, _ == _, _ == _) + val _ne = NumComparator(_ != _, _ != _, _ != _) + + implicit def booleanToDataEntry(b: Boolean): DataEntry = DataEntry(Array((if(b) 1 else 0).toByte), DataType.Boolean) + + def numBiComparation(x: DataEntry, y: DataEntry, comparator: NumComparator): Either[ValidationError, DataEntry] = + if (x.dataType == y.dataType) x.dataType match { + case Int32 => Right(comparator.int(x, y)) + case Amount => Right(comparator.long(x, y)) + case Timestamp => Right(comparator.long(x, y)) + case BigInteger => Right(comparator.bigInt(x, y)) + case _ => Left(ContractUnsupportedOPC) } else Left(ContractDataTypeMismatch) - } object CompareType extends Enumeration { - val Geq = Value(1) + sealed case class CompareTypeVal(compareType: Int, op: NumComparator) extends Val(compareType) { def *(n: Int): Int = n * compareType } + val Ge = CompareTypeVal(1, ge) + val Gt = CompareTypeVal(2, gt) + val Le = CompareTypeVal(3, le) + val Lt = CompareTypeVal(4, lt) + val Eq = CompareTypeVal(5, _eq) + val Ne = CompareTypeVal(6, _ne) } override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(CompareType(f)).toOption) match { - case Some(CompareType.Geq) if bytes.length == 4 => geq(data(bytes(1)), data(bytes(2)), data, bytes(3)) + case Some(t: CompareType.CompareTypeVal) if bytes.length == 4 && checkIndexes(bytes, data, Seq(1, 2)) => + updateStack(data, bytes.last, numBiComparation(data(bytes(1)), data(bytes(2)), t.op)) case _ => Left(ContractInvalidOPCData) } } diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala index 477e33d66..9b4c385b7 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala @@ -2,9 +2,11 @@ package vsys.blockchain.state.opcdiffs import com.google.common.primitives.Ints import vsys.blockchain.transaction.ValidationError -import vsys.blockchain.transaction.ValidationError.ContractUnsupportedOPC +import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} +import vsys.blockchain.contract.DataType._ +import scala.language.implicitConversions import scala.util.Try trait OpcDiffer { @@ -56,4 +58,23 @@ object OpcDiffer { def apply(context: ExecutionContext)(opc: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, (OpcDiff, Seq[DataEntry])] = opc.headOption.flatMap(OpcType.fromByte(_)).toRight(ContractUnsupportedOPC).flatMap(_.opcDiffer.parseBytes(context)(opc.tail, data)) + implicit def int2Byte(x:Int): Byte = x.toByte + + implicit def dataEntry2Int(x: DataEntry): Int = Int32.deserializer(x.data) + + implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) + + implicit def dataEntry2Long(x: DataEntry): Long = Amount.deserializer(x.data) // same as timestamp + + implicit def boolDataEntry2Byte(x: DataEntry): Byte = x.data(0) + + // res is call-by-name + def updateStack(dataStack: Seq[DataEntry], pointer: Byte, + res: => Either[ValidationError, DataEntry]): Either[ValidationError, Seq[DataEntry]] = + if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) + else res.map(r => dataStack.patch(pointer, Seq(r), 1)) + + // indexes.max < bytes.length is ensured before calling this + def checkIndexes(bytes: Array[Byte], dataStack: Seq[DataEntry], indexes: Seq[Int]): Boolean = + indexes.map(bytes(_)).filterNot(idx => idx < dataStack.length && idx >= 0).isEmpty } From ad4ad3850ebe82d6579d480ba6171fd2bd73da81 Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 25 Sep 2020 17:02:57 +0800 Subject: [PATCH 074/391] format fix --- .../vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala index a8c14e530..16e7d2e7a 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala @@ -41,10 +41,12 @@ object CompareOpcDiff extends OpcDiffer { val Ne = CompareTypeVal(6, _ne) } + def differ(bytes: Array[Byte], data: Seq[DataEntry], t: CompareType.CompareTypeVal) = + updateStack(data, bytes.last, numBiComparation(data(bytes(1)), data(bytes(2)), t.op)) + override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(CompareType(f)).toOption) match { - case Some(t: CompareType.CompareTypeVal) if bytes.length == 4 && checkIndexes(bytes, data, Seq(1, 2)) => - updateStack(data, bytes.last, numBiComparation(data(bytes(1)), data(bytes(2)), t.op)) + case Some(t: CompareType.CompareTypeVal) if bytes.length == 4 && checkIndexes(bytes, data, Seq(1, 2)) => differ(bytes, data, t) case _ => Left(ContractInvalidOPCData) } } From 601e32a43978f48ec7f5d2715deeb1c046cf1190 Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 25 Sep 2020 17:06:54 +0800 Subject: [PATCH 075/391] fix comment --- .../scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala index 9b4c385b7..b5a5a50c4 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala @@ -69,12 +69,11 @@ object OpcDiffer { implicit def boolDataEntry2Byte(x: DataEntry): Byte = x.data(0) // res is call-by-name - def updateStack(dataStack: Seq[DataEntry], pointer: Byte, - res: => Either[ValidationError, DataEntry]): Either[ValidationError, Seq[DataEntry]] = + def updateStack(dataStack: Seq[DataEntry], pointer: Byte, res: => Either[ValidationError, DataEntry]): Either[ValidationError, Seq[DataEntry]] = if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) else res.map(r => dataStack.patch(pointer, Seq(r), 1)) - // indexes.max < bytes.length is ensured before calling this + // indexes.max < bytes.length should be ensured before calling this def checkIndexes(bytes: Array[Byte], dataStack: Seq[DataEntry], indexes: Seq[Int]): Boolean = indexes.map(bytes(_)).filterNot(idx => idx < dataStack.length && idx >= 0).isEmpty } From 7bf8542903f147a7a1dd3f79897878bc5b29b62a Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 25 Sep 2020 17:17:27 +0800 Subject: [PATCH 076/391] make conver helper --- .../vsys/blockchain/contract/DataEntry.scala | 15 +++++++++++++++ .../blockchain/state/opcdiffs/BasicOpcDiff.scala | 1 + .../state/opcdiffs/CompareOpcDiff.scala | 3 ++- .../blockchain/state/opcdiffs/OpcDiffer.scala | 12 ------------ 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index e1e355b95..cf1498340 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -5,7 +5,9 @@ import play.api.libs.json.{JsObject, Json} import scorex.crypto.encode.Base58 import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError.InvalidDataEntry +import vsys.blockchain.contract.DataType._ +import scala.language.implicitConversions import scala.util.Success case class DataEntry(data: Array[Byte], @@ -85,4 +87,17 @@ object DataEntry { case Left(l) => Left(l) } } + + object ConvertHelper { + + implicit def int2Byte(x:Int): Byte = x.toByte + + implicit def dataEntry2Int(x: DataEntry): Int = Int32.deserializer(x.data) + + implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) + + implicit def dataEntry2Long(x: DataEntry): Long = Amount.deserializer(x.data) // same as timestamp + + implicit def boolDataEntry2Byte(x: DataEntry): Byte = x.data(0) + } } diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 52a85f18e..71052295d 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -4,6 +4,7 @@ import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} import vsys.blockchain.contract.DataType._ +import vsys.blockchain.contract.DataEntry.ConvertHelper._ import vsys.blockchain.state.opcdiffs.OpcDiffer._ import scala.language.implicitConversions diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala index 16e7d2e7a..6b4ad71cf 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala @@ -4,6 +4,7 @@ import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} import vsys.blockchain.contract.DataType._ +import vsys.blockchain.contract.DataEntry.ConvertHelper._ import vsys.blockchain.state.opcdiffs.OpcDiffer._ import scala.language.implicitConversions @@ -20,7 +21,7 @@ object CompareOpcDiff extends OpcDiffer { val _eq = NumComparator(_ == _, _ == _, _ == _) val _ne = NumComparator(_ != _, _ != _, _ != _) - implicit def booleanToDataEntry(b: Boolean): DataEntry = DataEntry(Array((if(b) 1 else 0).toByte), DataType.Boolean) + private implicit def booleanToDataEntry(b: Boolean): DataEntry = DataEntry(Array((if(b) 1 else 0).toByte), DataType.Boolean) def numBiComparation(x: DataEntry, y: DataEntry, comparator: NumComparator): Either[ValidationError, DataEntry] = if (x.dataType == y.dataType) x.dataType match { diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala index b5a5a50c4..c885f0111 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala @@ -4,9 +4,7 @@ import com.google.common.primitives.Ints import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.contract.{DataEntry, DataType, ExecutionContext} -import vsys.blockchain.contract.DataType._ -import scala.language.implicitConversions import scala.util.Try trait OpcDiffer { @@ -58,16 +56,6 @@ object OpcDiffer { def apply(context: ExecutionContext)(opc: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, (OpcDiff, Seq[DataEntry])] = opc.headOption.flatMap(OpcType.fromByte(_)).toRight(ContractUnsupportedOPC).flatMap(_.opcDiffer.parseBytes(context)(opc.tail, data)) - implicit def int2Byte(x:Int): Byte = x.toByte - - implicit def dataEntry2Int(x: DataEntry): Int = Int32.deserializer(x.data) - - implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) - - implicit def dataEntry2Long(x: DataEntry): Long = Amount.deserializer(x.data) // same as timestamp - - implicit def boolDataEntry2Byte(x: DataEntry): Byte = x.data(0) - // res is call-by-name def updateStack(dataStack: Seq[DataEntry], pointer: Byte, res: => Either[ValidationError, DataEntry]): Either[ValidationError, Seq[DataEntry]] = if (pointer > dataStack.length || pointer < 0) Left(ContractLocalVariableIndexOutOfRange) From e929af2f77974651ed13ad72183929e952ba7de3 Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 25 Sep 2020 18:06:42 +0800 Subject: [PATCH 077/391] bigint length cannot be zero --- src/main/scala/vsys/blockchain/contract/DataType.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index 3a6068482..45937b734 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -161,7 +161,7 @@ object DataType extends Enumeration { deserializer = b => BigInt(b.drop(2)), serializer = i => i.toByteArray, jsonifier = i => Json.toJson(i.toString), - extValidator = _ => true) + extValidator = b => b.length > 2) def fromByte(b: Byte): Option[DataTypeVal[_]] = Try(DataType(b).asInstanceOf[DataTypeVal[_]]).toOption From e0070ea04d01ba72f5c5bda30ba3336100f51f82 Mon Sep 17 00:00:00 2001 From: zl730 Date: Mon, 28 Sep 2020 12:18:11 +0800 Subject: [PATCH 078/391] fix bug and fix existing tests --- .../vsys/blockchain/contract/DataType.scala | 4 +- src/test/scala/tools/ContractTranslator.scala | 2 +- .../contract/DataEntrySpecification.scala | 11 +- .../contract/DataTypeSpecification.scala | 3 +- .../state/opcdiffs/BasicOpcDiffTest.scala | 255 +++++++----------- .../state/opcdiffs/CompareOpcDiffTest.scala | 20 +- .../transaction/TransactionGen.scala | 1 + 7 files changed, 117 insertions(+), 179 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index 45937b734..7885079cc 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -37,10 +37,10 @@ object DataType extends Enumeration { val DataTypeObj = DataTypeVal[DataTypeVal[_]](0, lenFixed = true, maxLen = 1, - deserializer = x => fromByte(x(1)).get, + deserializer = x => fromByte(x(0)).get, serializer = v => Array(v.id.toByte), jsonifier = v => Json.toJson(v.toString), - extValidator = x => fromByte(x(1)).nonEmpty) + extValidator = x => fromByte(x(0)).nonEmpty) val PublicKey = DataTypeVal[PublicKeyAccount](1, lenFixed = true, diff --git a/src/test/scala/tools/ContractTranslator.scala b/src/test/scala/tools/ContractTranslator.scala index a917483be..789dec863 100644 --- a/src/test/scala/tools/ContractTranslator.scala +++ b/src/test/scala/tools/ContractTranslator.scala @@ -342,7 +342,7 @@ object ContractTranslator extends App { case opcType: Byte if opcType == OpcType.CompareOpc.id => y match { - case opcType: Byte if opcType == CompareType.Geq.id => nameList(data(4)) + " = operation.compare.greater(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == CompareType.Ge.id => nameList(data(4)) + " = operation.compare.greater(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case _ => "--- invalid opc code ---" } diff --git a/src/test/scala/vsys/blockchain/contract/DataEntrySpecification.scala b/src/test/scala/vsys/blockchain/contract/DataEntrySpecification.scala index cd98f1904..206b9343f 100644 --- a/src/test/scala/vsys/blockchain/contract/DataEntrySpecification.scala +++ b/src/test/scala/vsys/blockchain/contract/DataEntrySpecification.scala @@ -52,7 +52,7 @@ class DataEntrySpecification extends PropSpec with PropertyChecks with Generator } yield DataEntry(data, DataType.OpcBlock) val validBigIntegerEntryGen: Gen[DataEntry] = for { - data <- attachmentGen.map(Deser.serializeArray) + data <- bigIntGen.map(Deser.serializeArray) } yield DataEntry(data, DataType.BigInteger) property("convert entry to bytes and convert back") { @@ -126,6 +126,8 @@ class DataEntrySpecification extends PropSpec with PropertyChecks with Generator property("report invalid and valid data type") { val byteArray1 = Array[Byte](0, 118, 97, 108, 117, 101, 49) + val byteArray1_1 = Array[Byte](0, 1) + val byteArray1_2 = Array[Byte](0, 20) val byteArray2 = Array[Byte](4, 118, 97, 108, 117, 101, 49) val byteArray3 = Array.fill[Byte](1 + 32)(1) val byteArray4 = Array.fill[Byte](1 + 26)(2) @@ -140,7 +142,10 @@ class DataEntrySpecification extends PropSpec with PropertyChecks with Generator val byteArray13 = Array[Byte](12, 118, 97, 108, 117, 101, 49) val byteArray14 = Array[Byte](13, 0, 0) val byteArray15 = Array[Byte](14, 0, 0) + val byteArray15_1 = Array[Byte](14, 0, 1, 100) DataEntry.fromBytes(byteArray1) should be (Left(InvalidDataEntry)) + DataEntry.fromBytes(byteArray1_1).map(_.dataType) should be (Right(DataType.DataTypeObj)) + DataEntry.fromBytes(byteArray1_2) should be (Left(InvalidDataEntry)) DataEntry.fromBytes(byteArray2) should be (Left(InvalidDataEntry)) DataEntry.fromBytes(byteArray3).map(_.dataType) should be (Right(DataType.PublicKey)) DataEntry.fromBytes(byteArray4).map(_.dataType) should be (Left(InvalidDataEntry)) @@ -154,7 +159,9 @@ class DataEntrySpecification extends PropSpec with PropertyChecks with Generator DataEntry.fromBytes(byteArray12).map(_.dataType) should be (Right(DataType.ShortBytes)) DataEntry.fromBytes(byteArray13).map(_.dataType) should be (Left(InvalidDataEntry)) DataEntry.fromBytes(byteArray14).map(_.dataType) should be (Right(DataType.OpcBlock)) - DataEntry.fromBytes(byteArray15).map(_.dataType) should be (Right(DataType.BigInteger)) + DataEntry.fromBytes(byteArray15).map(_.dataType) should be (Left(InvalidDataEntry)) + DataEntry.fromBytes(byteArray15_1).map(_.dataType) should be (Right(DataType.BigInteger)) + } private def assertEys(first: DataEntry, second: DataEntry): Unit = { diff --git a/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala b/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala index 6530101cf..d19485616 100644 --- a/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala +++ b/src/test/scala/vsys/blockchain/contract/DataTypeSpecification.scala @@ -6,7 +6,7 @@ import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} class DataTypeSpecification extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("convert byte to DataType") { - DataType.fromByte(0) should be (None) + DataType.fromByte(0) should be (Some(DataType.DataTypeObj)) DataType.fromByte(1) should be (Some(DataType.PublicKey)) DataType.fromByte(2) should be (Some(DataType.Address)) DataType.fromByte(3) should be (Some(DataType.Amount)) @@ -25,6 +25,7 @@ class DataTypeSpecification extends PropSpec with PropertyChecks with GeneratorD } property("convert DataType to byte") { + DataType.DataTypeObj.id should be (0) DataType.PublicKey.id should be (1) DataType.Address.id should be (2) DataType.Amount.id should be (3) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala index 62744531b..3e6356baa 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -6,267 +6,196 @@ import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.DataType.MaxShortBytesLength import vsys.blockchain.transaction.ValidationError -import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractLocalVariableIndexOutOfRange, - ContractUnsupportedOPC, InvalidDataEntry} +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractUnsupportedOPC, InvalidDataEntry} import scala.util.{Left, Right} class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test basic opcs") { - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.add) should be (Right(Seq(DataEntry(Longs.toByteArray(2), DataType.Amount)))) - BasicOpcDiff.operation( - DataEntry(Longs.toByteArray(1), DataType.Amount), - DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1, BasicOpcDiff.add) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.add) should be (Right(DataEntry(Longs.toByteArray(2), DataType.Amount))) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.add) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.add) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.add) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.operation( + BasicOpcDiff.add) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0, BasicOpcDiff.add) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.add) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 0, BasicOpcDiff.add) should be (Right(Seq(DataEntry( - Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger)))) - BasicOpcDiff.operation( - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 1, BasicOpcDiff.add) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.add) should be (Right(DataEntry( + Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger))) + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.add) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.add) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.minus) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) - BasicOpcDiff.operation( - DataEntry(Longs.toByteArray(1), DataType.Amount), - DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1, BasicOpcDiff.minus) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.minus) should be (Right(DataEntry(Longs.toByteArray(0), DataType.Amount))) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.minus) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), DataEntry(Longs.toByteArray(-1), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.operation( + BasicOpcDiff.minus) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.minus) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 0, BasicOpcDiff.minus) should be (Right(Seq(DataEntry( - Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger)))) - BasicOpcDiff.operation( - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 1, BasicOpcDiff.minus) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.minus) should be (Right(DataEntry( + Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger))) + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.minus) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.minus) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.multiply) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) - BasicOpcDiff.operation( - DataEntry(Longs.toByteArray(1), DataType.Amount), - DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1, BasicOpcDiff.multiply) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.multiply) should be (Right(DataEntry(Longs.toByteArray(1), DataType.Amount))) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.multiply) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount), DataEntry(Longs.toByteArray(2), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.operation( + BasicOpcDiff.multiply) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.multiply) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), - Seq.empty, 0, BasicOpcDiff.multiply) should be (Right(Seq(DataEntry( - Shorts.toByteArray(BigInt(4).toByteArray.length.toShort) ++ BigInt(4).toByteArray, DataType.BigInteger)))) - BasicOpcDiff.operation( + BasicOpcDiff.multiply) should be (Right(DataEntry( + Shorts.toByteArray(BigInt(4).toByteArray.length.toShort) ++ BigInt(4).toByteArray, DataType.BigInteger))) + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray((BigInt(1) << 255*8).toByteArray.length.toShort) ++ (BigInt(1) << 255*8).toByteArray, DataType.BigInteger), DataEntry(Shorts.toByteArray((BigInt(1) << 255*8).toByteArray.length.toShort) ++ (BigInt(1) << 255*8).toByteArray, DataType.BigInteger), - Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.operation( - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 1, BasicOpcDiff.multiply) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.multiply) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.multiply) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.multiply) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.divide) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) - BasicOpcDiff.operation( - DataEntry(Longs.toByteArray(1), DataType.Amount), - DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1, BasicOpcDiff.divide) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.divide) should be (Right(DataEntry(Longs.toByteArray(1), DataType.Amount))) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.divide) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.operation( + BasicOpcDiff.divide) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.divide) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), - Seq.empty, 0, BasicOpcDiff.divide) should be (Right(Seq(DataEntry( - Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger)))) - BasicOpcDiff.operation( + BasicOpcDiff.divide) should be (Right(DataEntry( + Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger))) + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.operation( - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 1, BasicOpcDiff.divide) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.divide) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.divide) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.divide) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.minimum) should be (Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) - BasicOpcDiff.operation( - DataEntry(Longs.toByteArray(1), DataType.Amount), - DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 1, BasicOpcDiff.minimum) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.minimum) should be (Right(DataEntry(Longs.toByteArray(0), DataType.Amount))) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.minimum) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.minimum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0, BasicOpcDiff.minimum) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.minimum) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), - Seq.empty, 0, BasicOpcDiff.minimum) should be (Right(Seq(DataEntry( - Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger)))) - BasicOpcDiff.operation( - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 1, BasicOpcDiff.minimum) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.minimum) should be (Right(DataEntry( + Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger))) + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.minimum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.minimum) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 0, BasicOpcDiff.maximum) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) - BasicOpcDiff.operation( - DataEntry(Longs.toByteArray(1), DataType.Amount), - DataEntry(Longs.toByteArray(0), DataType.Amount), - Seq.empty, 1, BasicOpcDiff.maximum) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.maximum) should be (Right(DataEntry(Longs.toByteArray(1), DataType.Amount))) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.maximum) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.operation( + BasicOpcDiff.maximum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.ShortText), DataEntry(Longs.toByteArray(1), DataType.ShortText), - Seq.empty, 0, BasicOpcDiff.maximum) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.maximum) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.operation( + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), - Seq.empty, 0, BasicOpcDiff.maximum) should be (Right(Seq(DataEntry( - Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger)))) - BasicOpcDiff.operation( - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), - Seq.empty, 1, BasicOpcDiff.maximum) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.operation( + BasicOpcDiff.maximum) should be (Right(DataEntry( + Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger))) + BasicOpcDiff.numBiOperation( DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), DataEntry(Longs.toByteArray(1), DataType.Timestamp), - Seq.empty, 0, BasicOpcDiff.maximum) should be (Left(ContractDataTypeMismatch)) + BasicOpcDiff.maximum) should be (Left(ContractDataTypeMismatch)) - BasicOpcDiff.sqrt( - DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, - 0) should be (Left(ContractUnsupportedOPC)) - BasicOpcDiff.sqrt( - DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger), - Seq.empty, - 1) should be (Left(ContractLocalVariableIndexOutOfRange)) - BasicOpcDiff.sqrt( - DataEntry(Shorts.toByteArray(BigInt(-1).toByteArray.length.toShort) ++ BigInt(-1).toByteArray, DataType.BigInteger), - Seq.empty, - 0) should be (Left(ValidationError.OverflowError)) - BasicOpcDiff.sqrt( - DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger), - Seq.empty, - 0) should be (Right(Seq(DataEntry( - Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger)))) - BasicOpcDiff.sqrt( - DataEntry(Shorts.toByteArray(BigInt(4).toByteArray.length.toShort) ++ BigInt(4).toByteArray, DataType.BigInteger), - Seq.empty, - 0) should be (Right(Seq(DataEntry( - Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger)))) + BasicOpcDiff.sqrt(DataEntry(Longs.toByteArray(1), DataType.Amount)) should be (Left(ContractUnsupportedOPC)) + BasicOpcDiff.sqrt(DataEntry(Shorts.toByteArray(BigInt(-1).toByteArray.length.toShort) ++ BigInt(-1).toByteArray, DataType.BigInteger) + ) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.sqrt(DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger) + ) should be (Right(DataEntry(Shorts.toByteArray(BigInt(1).toByteArray.length.toShort) ++ BigInt(1).toByteArray, DataType.BigInteger))) + BasicOpcDiff.sqrt(DataEntry(Shorts.toByteArray(BigInt(4).toByteArray.length.toShort) ++ BigInt(4).toByteArray, DataType.BigInteger) + ) should be (Right(DataEntry(Shorts.toByteArray(BigInt(2).toByteArray.length.toShort) ++ BigInt(2).toByteArray, DataType.BigInteger))) BasicOpcDiff.concat( DataEntry(Longs.toByteArray(1), DataType.Amount), - DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 0) should be ( - Right(Seq(DataEntry.create(Longs.toByteArray(1) ++ Longs.toByteArray(1), - DataType.ShortBytes).right.get))) - BasicOpcDiff.concat( - DataEntry(Longs.toByteArray(1), DataType.Amount), - DataEntry(Longs.toByteArray(1), DataType.Amount), - Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + DataEntry(Longs.toByteArray(1), DataType.Amount)) should be ( + Right(DataEntry.create(Longs.toByteArray(1) ++ Longs.toByteArray(1), + DataType.ShortBytes).right.get)) BasicOpcDiff.concat( DataEntry(Array.fill(MaxShortBytesLength){0}, DataType.ShortBytes), DataEntry(Array.fill(1){0}, DataType.ShortBytes), - Seq.empty, 0) should be (Left(InvalidDataEntry)) + ) should be (Left(InvalidDataEntry)) BasicOpcDiff.constantGet(Array(DataType.Amount.id.toByte) ++ Longs.toByteArray(1), - Seq.empty, 0) should be (Right(Seq(DataEntry(Longs.toByteArray(1), DataType.Amount)))) + ) should be (Right(DataEntry(Longs.toByteArray(1), DataType.Amount))) BasicOpcDiff.constantGet(Array(DataType.Amount.id.toByte) ++ Ints.toByteArray(1), - Seq.empty, 0) should be (Left(InvalidDataEntry)) - BasicOpcDiff.constantGet(Array(DataType.Amount.id.toByte) ++ Longs.toByteArray(1), - Seq.empty, 1) should be (Left(ContractLocalVariableIndexOutOfRange)) + ) should be (Left(InvalidDataEntry)) } } diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala index 7c583eeb1..c3f319da8 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiffTest.scala @@ -11,17 +11,17 @@ import scala.util.{Left, Right} class CompareOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { property("test compare opcs") { - CompareOpcDiff.geq(DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry( - Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be ( - Right(Seq(DataEntry(Array(1.toByte), DataType.Boolean)))) - CompareOpcDiff.geq(DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( - Longs.toByteArray(1), DataType.Amount), Seq.empty, 0) should be ( - Right(Seq(DataEntry(Array(0.toByte), DataType.Boolean)))) - CompareOpcDiff.geq(DataEntry(Ints.toByteArray(0), DataType.Int32), DataEntry( - Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + CompareOpcDiff.numBiComparation(DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Amount), CompareOpcDiff.ge) should be ( + Right(DataEntry(Array(1.toByte), DataType.Boolean))) + CompareOpcDiff.numBiComparation(DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Longs.toByteArray(1), DataType.Amount), CompareOpcDiff.ge) should be ( + Right(DataEntry(Array(0.toByte), DataType.Boolean))) + CompareOpcDiff.numBiComparation(DataEntry(Ints.toByteArray(0), DataType.Balance), DataEntry( + Ints.toByteArray(1), DataType.Balance), CompareOpcDiff.ge) should be ( Left(ContractUnsupportedOPC)) - CompareOpcDiff.geq(DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( - Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( + CompareOpcDiff.numBiComparation(DataEntry(Longs.toByteArray(0), DataType.Amount), DataEntry( + Ints.toByteArray(1), DataType.Int32), CompareOpcDiff.ge) should be ( Left(ContractDataTypeMismatch)) } } diff --git a/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala b/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala index 57d42a35c..0dee002fc 100644 --- a/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala +++ b/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala @@ -80,6 +80,7 @@ trait TransactionGen { val feeScaleGen: Gen[Short] = Gen.const(100) val slotidGen: Gen[Int] = Gen.choose(0, TestFunctionalitySettings.Enabled.numOfSlots - 1) val attachmentGen: Gen[Array[Byte]] = genBoundedBytes(0, PaymentTransaction.MaxAttachmentSize) + val bigIntGen: Gen[Array[Byte]] = genBoundedBytes(1, PaymentTransaction.MaxAttachmentSize) val entryGen: Gen[Entry] = for { data: String <- entryDataStringGen } yield Entry.buildEntry(data, DatabaseDataType.ByteArray).explicitGet() From f0360323230c3b6ac52978ff005aee72ccc30fa3 Mon Sep 17 00:00:00 2001 From: zl730 Date: Tue, 29 Sep 2020 12:18:00 +0800 Subject: [PATCH 079/391] fix bugs --- src/main/scala/vsys/blockchain/contract/DataEntry.scala | 4 ++-- src/main/scala/vsys/blockchain/contract/DataType.scala | 2 +- .../scala/vsys/blockchain/transaction/TransactionGen.scala | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index cf1498340..02e0fc39a 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -92,11 +92,11 @@ object DataEntry { implicit def int2Byte(x:Int): Byte = x.toByte - implicit def dataEntry2Int(x: DataEntry): Int = Int32.deserializer(x.data) + implicit def dataEntry2Int(x: DataEntry): Int = Ints.fromByteArray(x.data) implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) - implicit def dataEntry2Long(x: DataEntry): Long = Amount.deserializer(x.data) // same as timestamp + implicit def dataEntry2Long(x: DataEntry): Long = Longs.fromByteArray(x.data) // same as timestamp implicit def boolDataEntry2Byte(x: DataEntry): Byte = x.data(0) } diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index 7885079cc..0db70f415 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -15,7 +15,7 @@ object DataType extends Enumeration { val MaxShortTextLength = 140 val MaxShortBytesLength = 255 val MaxOpcBlockLength = 255 - val MaxBigIntLength = 255 // less than 1024 bits + val MaxBigIntLength = 255 // less than 2048 bits sealed case class DataTypeVal[T](dataType: Int, lenFixed: Boolean, maxLen: Int, deserializer: Array[Byte] => T, // take bytes WITH length prefix if length not fixed diff --git a/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala b/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala index 0dee002fc..89f03775b 100644 --- a/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala +++ b/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala @@ -80,7 +80,7 @@ trait TransactionGen { val feeScaleGen: Gen[Short] = Gen.const(100) val slotidGen: Gen[Int] = Gen.choose(0, TestFunctionalitySettings.Enabled.numOfSlots - 1) val attachmentGen: Gen[Array[Byte]] = genBoundedBytes(0, PaymentTransaction.MaxAttachmentSize) - val bigIntGen: Gen[Array[Byte]] = genBoundedBytes(1, PaymentTransaction.MaxAttachmentSize) + val bigIntGen: Gen[Array[Byte]] = genBoundedBytes(1, DataType.MaxBigIntLength) val entryGen: Gen[Entry] = for { data: String <- entryDataStringGen } yield Entry.buildEntry(data, DatabaseDataType.ByteArray).explicitGet() From 24ec06290df70717d1ccde52652268688d76c7b1 Mon Sep 17 00:00:00 2001 From: zl730 Date: Tue, 29 Sep 2020 12:20:55 +0800 Subject: [PATCH 080/391] import libs --- src/main/scala/vsys/blockchain/contract/DataEntry.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index 02e0fc39a..aacd30651 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -1,6 +1,6 @@ package vsys.blockchain.contract -import com.google.common.primitives.{Shorts, Bytes} +import com.google.common.primitives.{Shorts, Bytes, Longs, Ints} import play.api.libs.json.{JsObject, Json} import scorex.crypto.encode.Base58 import vsys.blockchain.transaction.ValidationError @@ -96,7 +96,7 @@ object DataEntry { implicit def dataEntry2BigInt(x: DataEntry): BigInt = BigInteger.deserializer(x.data) - implicit def dataEntry2Long(x: DataEntry): Long = Longs.fromByteArray(x.data) // same as timestamp + implicit def dataEntry2Long(x: DataEntry): Long = Longs.fromByteArray(x.data) implicit def boolDataEntry2Byte(x: DataEntry): Byte = x.data(0) } From c3165b99a63e5e5a490183c1cd8d3389293b468b Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 6 Oct 2020 10:17:29 +0800 Subject: [PATCH 081/391] add state var add and minus --- .../state/opcdiffs/CDBVOpcDiff.scala | 86 +++++++++++++++---- 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiff.scala index 9c32c4f00..893d0c6dd 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiff.scala @@ -36,43 +36,87 @@ object CDBVOpcDiff extends OpcDiffer { } yield diff } - def mapValueAdd(context: ExecutionContext)(stateMap: Array[Byte], - keyValue: DataEntry, dataValue: DataEntry): Either[ValidationError, OpcDiff] = { - val combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes) - if (!checkStateMap(stateMap, keyValue.dataType, dataValue.dataType)) { - Left(ContractInvalidStateMap) - } else if (dataValue.dataType == DataType.Amount) { - val cntBalance = context.state.contractNumInfo(combinedKey) - val addAmount = Longs.fromByteArray(dataValue.data) + private def numDBAddChange(context: ExecutionContext)(value: DataEntry, dbKey: ByteStr): Either[ValidationError, Long] = { + if (value.dataType == DataType.Amount) { + val cntBalance = context.state.contractNumInfo(dbKey) + val addAmount = Longs.fromByteArray(value.data) if (addAmount < 0){ Left(InvalidDataEntry) } else if (Try(Math.addExact(cntBalance, addAmount)).isFailure) Left(ValidationError.OverflowError) else - Right(OpcDiff(contractNumDB = Map(combinedKey -> addAmount))) + Right(addAmount) } else Left(ContractDataTypeMismatch) } - def mapValueMinus(context: ExecutionContext)(stateMap: Array[Byte], - keyValue: DataEntry, dataValue: DataEntry): Either[ValidationError, OpcDiff] = { - val combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes) - if (!checkStateMap(stateMap, keyValue.dataType, dataValue.dataType)) { - Left(ContractInvalidStateMap) - } else if (dataValue.dataType == DataType.Amount) { - val cntBalance = context.state.contractNumInfo(combinedKey) - val minusAmount = Longs.fromByteArray(dataValue.data) + private def numDBMinusChange(context: ExecutionContext)(value: DataEntry, dbKey: ByteStr): Either[ValidationError, Long] = { + if (value.dataType == DataType.Amount) { + val cntBalance = context.state.contractNumInfo(dbKey) + val minusAmount = Longs.fromByteArray(value.data) if (minusAmount < 0){ Left(InvalidDataEntry) } else if (cntBalance >= minusAmount) - Right(OpcDiff(contractNumDB = Map(combinedKey -> -minusAmount))) + Right(-minusAmount) else Left(ContractMapValueInsufficient) } else Left(ContractDataTypeMismatch) } + def mapValueAdd(context: ExecutionContext)(stateMap: Array[Byte], + keyValue: DataEntry, dataValue: DataEntry): Either[ValidationError, OpcDiff] = { + for { + _ <- Either.cond(checkStateMap(stateMap, keyValue.dataType, dataValue.dataType), (), ContractInvalidStateMap) + combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes) + updateAmount <- numDBAddChange(context)(dataValue, combinedKey) + diff = OpcDiff(contractNumDB = Map(combinedKey -> updateAmount)) + } yield diff + } + + def mapValueMinus(context: ExecutionContext)(stateMap: Array[Byte], + keyValue: DataEntry, dataValue: DataEntry): Either[ValidationError, OpcDiff] = { + for { + _ <- Either.cond(checkStateMap(stateMap, keyValue.dataType, dataValue.dataType), (), ContractInvalidStateMap) + combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes) + updateAmount <- numDBMinusChange(context)(dataValue, combinedKey) + diff = OpcDiff(contractNumDB = Map(combinedKey -> updateAmount)) + } yield diff + } + + def valueAdd(context: ExecutionContext)(stateVar: Array[Byte], + value: DataEntry): Either[ValidationError, OpcDiff] = { + for { + _ <- Either.cond(checkStateVar(stateVar, value.dataType), (), ContractInvalidStateVariable) + addrOpt <- if (value.dataType == DataType.Address) Address.fromBytes(value.data).map(Some(_)) + else Right(None) + combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateVar(0))) + updateAmount <- numDBAddChange(context)(value, combinedKey) + contractNumDB = Map(combinedKey -> updateAmount) + diff = addrOpt match { + case Some(addr) => OpcDiff(relatedAddress = Map(addr -> true), contractNumDB = contractNumDB) + case None => OpcDiff(contractNumDB = contractNumDB) + } + } yield diff + } + + def valueMinus(context: ExecutionContext)(stateVar: Array[Byte], + value: DataEntry): Either[ValidationError, OpcDiff] = { + for { + _ <- Either.cond(checkStateVar(stateVar, value.dataType), (), ContractInvalidStateVariable) + addrOpt <- if (value.dataType == DataType.Address) Address.fromBytes(value.data).map(Some(_)) + else Right(None) + combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateVar(0))) + updateAmount <- numDBMinusChange(context)(value, combinedKey) + contractNumDB = Map(combinedKey -> updateAmount) + diff = addrOpt match { + case Some(addr) => OpcDiff(relatedAddress = Map(addr -> true), contractNumDB = contractNumDB) + case None => OpcDiff(contractNumDB = contractNumDB) + } + } yield diff + } + object CDBVType extends Enumeration(1) { - val SetCDBV, mapSetCDBV, mapValueAddCDBV, mapValueMinusCDBV = Value + val SetCDBV, mapSetCDBV, mapValueAddCDBV, mapValueMinusCDBV, stateValueAddCDBV, stateValueMinusCDBV = Value } private def checkCDBVBytes(bytes: Array[Byte], dLength: Int, stateVarOrMapSize: Int): Boolean = @@ -88,6 +132,10 @@ object CDBVOpcDiff extends OpcDiffer { mapValueAdd(context)(context.stateMap(bytes(1)), data(bytes(2)), data(bytes(3))) case (Some(CDBVType.mapValueMinusCDBV), 4) if checkCDBVBytes(bytes, data.length, context.stateMap.length) => mapValueMinus(context)(context.stateMap(bytes(1)), data(bytes(2)), data(bytes(3))) + case (Some(CDBVType.stateValueAddCDBV), 3) if checkCDBVBytes(bytes, data.length, context.stateVar.length) => + valueAdd(context)(context.stateVar(bytes(1)), data(bytes(2))) + case (Some(CDBVType.stateValueMinusCDBV), 3) if checkCDBVBytes(bytes, data.length, context.stateVar.length) => + valueMinus(context)(context.stateVar(bytes(1)), data(bytes(2))) case _ => Left(ContractInvalidOPCData) } } From d65f22b53ae74c434c0c629f3d199d0cb3d274c4 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 6 Oct 2020 10:18:17 +0800 Subject: [PATCH 082/391] update state var add minus test --- .../state/opcdiffs/CDBVOpcDiffTest.scala | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala index b7c30770d..b15063fbd 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVOpcDiffTest.scala @@ -91,5 +91,36 @@ class CDBVOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenP Array[Byte](0.toByte, 3.toByte, 4.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), DataEntry( Longs.toByteArray(1), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) + + CDBVOpcDiff.valueAdd(executionContext)( + Array[Byte](0.toByte, 3.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount)).right.get.contractNumDB( + ByteStr(tx.contractId.bytes.arr ++ Array[Byte](0.toByte))) shouldEqual 0 + CDBVOpcDiff.valueAdd(executionContext)( + Array[Byte](0.toByte, 2.toByte), DataEntry( + Longs.toByteArray(0), DataType.ShortBytes)) should be (Left(ContractInvalidStateVariable)) + CDBVOpcDiff.valueAdd(executionContext)( + Array[Byte](0.toByte, 3.toByte), DataEntry( + Longs.toByteArray(-1), DataType.Amount)) should be (Left(InvalidDataEntry)) + CDBVOpcDiff.valueAdd(executionContext)( + Array[Byte](0.toByte, 4.toByte), DataEntry( + Longs.toByteArray(1), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) + + CDBVOpcDiff.valueMinus(executionContext)( + Array[Byte](0.toByte, 3.toByte), DataEntry( + Longs.toByteArray(0), DataType.Amount)).right.get.contractNumDB( + ByteStr(tx.contractId.bytes.arr ++ Array[Byte](0.toByte))) shouldEqual 0 + CDBVOpcDiff.valueMinus(executionContext)( + Array[Byte](0.toByte, 2.toByte), DataEntry( + Longs.toByteArray(0), DataType.ShortBytes)) should be (Left(ContractInvalidStateVariable)) + CDBVOpcDiff.valueMinus(executionContext)( + Array[Byte](0.toByte, 3.toByte), DataEntry( + Longs.toByteArray(-1), DataType.Amount)) should be (Left(InvalidDataEntry)) + CDBVOpcDiff.valueMinus(executionContext)( + Array[Byte](0.toByte, 3.toByte), DataEntry( + Longs.toByteArray(1), DataType.Amount)) should be (Left(ContractMapValueInsufficient)) + CDBVOpcDiff.valueMinus(executionContext)( + Array[Byte](0.toByte, 4.toByte), DataEntry( + Longs.toByteArray(1), DataType.Int32)) should be (Left(ContractDataTypeMismatch)) } } From 1eee493168a993d0467b65475c28084d47d8f4a5 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 6 Oct 2020 10:18:46 +0800 Subject: [PATCH 083/391] add state var get or default --- .../state/opcdiffs/CDBVROpcDiff.scala | 89 +++++++++++-------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala index 408772793..c586639a4 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala @@ -11,55 +11,70 @@ import scala.util.{Left, Right, Try} object CDBVROpcDiff extends OpcDiffer { + private def dbGet(context: ExecutionContext)(dbKey: ByteStr, dataTypeByte: Byte): Either[ValidationError, DataEntry] = { + context.state.contractInfo(dbKey) match { + case Some(v) => Right(v) + case _ => Left(GenericError("Can not find the data.")) + } + } + + private def dbGetOrDefault(context: ExecutionContext)(dbKey: ByteStr, dataTypeByte: Byte): Either[ValidationError, DataEntry] = { + context.state.contractInfo(dbKey) match { + case Some(v) => Right(v) + case _ if DataType(dataTypeByte) == DataType.Timestamp => + Right(DataEntry(Longs.toByteArray(0L), DataType.Timestamp)) + case _ if DataType(dataTypeByte) == DataType.Amount => + Right(DataEntry(Longs.toByteArray(context.state.contractNumInfo(dbKey)), DataType.Amount)) + case _ => Left(GenericError("Can not find the data.")) + } + } + def get(context: ExecutionContext)(stateVar: Array[Byte], dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateVar(stateVar)) { - Left(ContractInvalidStateVariable) - } else if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - context.state.contractInfo(ByteStr(context.contractId.bytes.arr ++ Array(stateVar(0)))) match { - case Some(v) => Right(dataStack.patch(pointer, Seq(v), 1)) - case _ => Left(ContractStateVariableNotDefined) - } - } + for { + _ <- Either.cond(checkStateVar(stateVar), (), ContractInvalidStateVariable) + _ <- Either.cond(pointer <= dataStack.length && pointer >= 0, (), ContractLocalVariableIndexOutOfRange) + combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateVar(0))) + updatedDataEntry <- dbGet(context)(combinedKey, stateVar(1)).left.map(_ => ContractStateVariableNotDefined) + updatedSeq = dataStack.patch(pointer, Seq(updatedDataEntry), 1) + } yield updatedSeq } def mapGet(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateMap(stateMap, keyValue.dataType)) { - Left(ContractInvalidStateMap) - } else if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - val combinedKey = context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes - context.state.contractInfo(ByteStr(combinedKey)) match { - case Some(v) => Right(dataStack.patch(pointer, Seq(v), 1)) - case _ => Left(ContractStateMapNotDefined) - } - } + for { + _ <- Either.cond(checkStateMap(stateMap, keyValue.dataType), (), ContractInvalidStateMap) + _ <- Either.cond(pointer <= dataStack.length && pointer >= 0, (), ContractLocalVariableIndexOutOfRange) + combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes) + updatedDataEntry <- dbGet(context)(combinedKey, stateMap(2)).left.map(_ => ContractStateMapNotDefined) + updatedSeq = dataStack.patch(pointer, Seq(updatedDataEntry), 1) + } yield updatedSeq } def mapGetOrDefault(context: ExecutionContext)(stateMap: Array[Byte], keyValue: DataEntry, dataStack: Seq[DataEntry], pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { - if (!checkStateMap(stateMap, keyValue.dataType)) { - Left(ContractInvalidStateMap) - } else if (pointer > dataStack.length || pointer < 0) { - Left(ContractLocalVariableIndexOutOfRange) - } else { - val combinedKey = context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes - 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) - } - } + for { + _ <- Either.cond(checkStateMap(stateMap, keyValue.dataType), (), ContractInvalidStateMap) + _ <- Either.cond(pointer <= dataStack.length && pointer >= 0, (), ContractLocalVariableIndexOutOfRange) + combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes) + updatedDataEntry <- dbGetOrDefault(context)(combinedKey, stateMap(2)).left.map(_ => ContractStateMapNotDefined) + updatedSeq = dataStack.patch(pointer, Seq(updatedDataEntry), 1) + } yield updatedSeq + } + + def getOrDefault(context: ExecutionContext)(stateVar: Array[Byte], dataStack: Seq[DataEntry], + pointer: Byte): Either[ValidationError, Seq[DataEntry]] = { + for { + _ <- Either.cond(checkStateVar(stateVar), (), ContractInvalidStateVariable) + _ <- Either.cond(pointer <= dataStack.length && pointer >= 0, (), ContractLocalVariableIndexOutOfRange) + combinedKey = ByteStr(context.contractId.bytes.arr ++ Array(stateVar(0))) + updatedDataEntry <- dbGetOrDefault(context)(combinedKey, stateVar(1)).left.map(_ => ContractStateVariableNotDefined) + updatedSeq = dataStack.patch(pointer, Seq(updatedDataEntry), 1) + } yield updatedSeq } object CDBVRType extends Enumeration(1) { - val GetCDBVR, MapGetOrDefaultCDBVR, MapGetCDVVR = Value + val GetCDBVR, MapGetOrDefaultCDBVR, MapGetCDVVR, StateVarGetOrDefaultCDBVR = Value } private def checkCDBVRIndex(bytes: Array[Byte], id: Int, stateVarOrMapSize: Int): Boolean = @@ -73,6 +88,8 @@ object CDBVROpcDiff extends OpcDiffer { bytes(2) <= data.length => mapGetOrDefault(context)(context.stateMap(bytes(1)), data(bytes(2)), data, bytes(3)) case (Some(CDBVRType.MapGetCDVVR), 4) if checkCDBVRIndex(bytes, 1, context.stateMap.length) && bytes(2) >=0 && bytes(2) <= data.length => mapGet(context)(context.stateMap(bytes(1)), data(bytes(2)), data, bytes(3)) + case (Some(CDBVRType.StateVarGetOrDefaultCDBVR), 3) if checkCDBVRIndex(bytes, 1, context.stateVar.length) => + getOrDefault(context)(context.stateVar(bytes(1)), data, bytes(2)) case _ => Left(ContractInvalidOPCData) } } From d800252e7b5d385b73f65c1c31ad52cf04c4b850 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 6 Oct 2020 10:19:20 +0800 Subject: [PATCH 084/391] add state var get or default test --- .../state/opcdiffs/CDBVROpcDiffTest.scala | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala index 93706cfde..a557e7325 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala @@ -8,8 +8,7 @@ import vsys.blockchain.contract.{ContractPermitted, DataEntry, DataType, Executi import vsys.blockchain.state.StateWriterImpl import vsys.blockchain.state.diffs.newState import vsys.blockchain.transaction.TransactionParser -import vsys.blockchain.transaction.ValidationError.{ContractInvalidStateMap, ContractLocalVariableIndexOutOfRange, - ContractStateMapNotDefined, ContractStateVariableNotDefined} +import vsys.blockchain.transaction.ValidationError._ import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.settings.TestFunctionalitySettings @@ -67,5 +66,18 @@ class CDBVROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Longs.toByteArray(1), DataType.Amount), Seq.empty, 1) should be ( Left(ContractLocalVariableIndexOutOfRange)) + + CDBVROpcDiff.getOrDefault(executionContext)( + Array[Byte](0.toByte, 3.toByte), Seq.empty, 0) should be ( + Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Amount)))) + CDBVROpcDiff.getOrDefault(executionContext)( + Array[Byte](0.toByte, 9.toByte), Seq.empty, 0) should be ( + Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Timestamp)))) + CDBVROpcDiff.getOrDefault(executionContext)( + Array[Byte](0.toByte, 4.toByte), Seq.empty, 0) should be ( + Left(ContractStateVariableNotDefined)) + CDBVROpcDiff.getOrDefault(executionContext)( + Array[Byte](0.toByte, 3.toByte), Seq.empty, 1) should be ( + Left(ContractLocalVariableIndexOutOfRange)) } } From ec332b1bf2da17d96ca988422999d86e4b8ce5bc Mon Sep 17 00:00:00 2001 From: zl730 Date: Wed, 14 Oct 2020 13:47:58 +0800 Subject: [PATCH 085/391] add eq and neq for general data entry --- .../state/opcdiffs/CompareOpcDiff.scala | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala index 6b4ad71cf..cb56ffc43 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala @@ -12,6 +12,8 @@ import scala.util.{Left, Right, Try} object CompareOpcDiff extends OpcDiffer { + + case class NumComparator(int: (Int, Int) => Boolean, long: (Long, Long) => Boolean, bigInt: (BigInt, BigInt) => Boolean) val ge = NumComparator(_ >= _, _ >= _, _ >= _) @@ -33,21 +35,29 @@ object CompareOpcDiff extends OpcDiffer { } else Left(ContractDataTypeMismatch) object CompareType extends Enumeration { - sealed case class CompareTypeVal(compareType: Int, op: NumComparator) extends Val(compareType) { def *(n: Int): Int = n * compareType } - val Ge = CompareTypeVal(1, ge) - val Gt = CompareTypeVal(2, gt) - val Le = CompareTypeVal(3, le) - val Lt = CompareTypeVal(4, lt) - val Eq = CompareTypeVal(5, _eq) - val Ne = CompareTypeVal(6, _ne) + sealed case class NumCompareTypeVal(compareType: Int, op: NumComparator) extends Val(compareType) { def *(n: Int): Int = n * compareType } + val Ge = NumCompareTypeVal(1, ge) + val Gt = NumCompareTypeVal(2, gt) + val Le = NumCompareTypeVal(3, le) + val Lt = NumCompareTypeVal(4, lt) + val Eq = NumCompareTypeVal(5, _eq) + val Ne = NumCompareTypeVal(6, _ne) + val Beq = new Val(7) + val Bne = new Val(8) } - def differ(bytes: Array[Byte], data: Seq[DataEntry], t: CompareType.CompareTypeVal) = + def numDiffer(bytes: Array[Byte], data: Seq[DataEntry], t: CompareType.NumCompareTypeVal) = updateStack(data, bytes.last, numBiComparation(data(bytes(1)), data(bytes(2)), t.op)) + def bytesDiffer(bytes: Array[Byte], data: Seq[DataEntry], op: (DataEntry, DataEntry) => Boolean) = + updateStack(data, bytes.last, Right(op(data(bytes(1)), data(bytes(2))))) + + private val ensured = (b: Array[Byte], d: Seq[DataEntry]) => b.length == 4 && checkIndexes(b, d, Seq(1, 2)) override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(CompareType(f)).toOption) match { - case Some(t: CompareType.CompareTypeVal) if bytes.length == 4 && checkIndexes(bytes, data, Seq(1, 2)) => differ(bytes, data, t) + case Some(t: CompareType.NumCompareTypeVal) if ensured(bytes, data) => numDiffer(bytes, data, t) + case Some(CompareType.Beq) if ensured(bytes, data) => bytesDiffer(bytes, data, _ == _) + case Some(CompareType.Bne) if ensured(bytes, data) => bytesDiffer(bytes, data, _ != _) case _ => Left(ContractInvalidOPCData) } } From f081b5ea198f07489014f9f258cb22e573341bcf Mon Sep 17 00:00:00 2001 From: zl730 Date: Wed, 14 Oct 2020 14:02:06 +0800 Subject: [PATCH 086/391] optimize code structure --- .../state/opcdiffs/CompareOpcDiff.scala | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala index cb56ffc43..ca206996f 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala @@ -35,29 +35,30 @@ object CompareOpcDiff extends OpcDiffer { } else Left(ContractDataTypeMismatch) object CompareType extends Enumeration { - sealed case class NumCompareTypeVal(compareType: Int, op: NumComparator) extends Val(compareType) { def *(n: Int): Int = n * compareType } - val Ge = NumCompareTypeVal(1, ge) - val Gt = NumCompareTypeVal(2, gt) - val Le = NumCompareTypeVal(3, le) - val Lt = NumCompareTypeVal(4, lt) - val Eq = NumCompareTypeVal(5, _eq) - val Ne = NumCompareTypeVal(6, _ne) - val Beq = new Val(7) - val Bne = new Val(8) + class CompareTypeVal(compareType: Int) extends Val(compareType) { def *(n: Int): Int = n * compareType } + sealed case class NumCompareTypeVal(compareType: Int, op: NumComparator) extends CompareTypeVal(compareType) + sealed case class BytesCompareTypeVal(compareType: Int, op: (DataEntry, DataEntry) => Boolean) extends CompareTypeVal(compareType) + val Ge = NumCompareTypeVal(1, ge) + val Gt = NumCompareTypeVal(2, gt) + val Le = NumCompareTypeVal(3, le) + val Lt = NumCompareTypeVal(4, lt) + val Eq = NumCompareTypeVal(5, _eq) + val Ne = NumCompareTypeVal(6, _ne) + val Beq = BytesCompareTypeVal(7, _ == _) + val Bne = BytesCompareTypeVal(8, _ != _) } - def numDiffer(bytes: Array[Byte], data: Seq[DataEntry], t: CompareType.NumCompareTypeVal) = + def differ(bytes: Array[Byte], data: Seq[DataEntry], t: CompareType.NumCompareTypeVal) = updateStack(data, bytes.last, numBiComparation(data(bytes(1)), data(bytes(2)), t.op)) - def bytesDiffer(bytes: Array[Byte], data: Seq[DataEntry], op: (DataEntry, DataEntry) => Boolean) = - updateStack(data, bytes.last, Right(op(data(bytes(1)), data(bytes(2))))) + def differ(bytes: Array[Byte], data: Seq[DataEntry], t: CompareType.BytesCompareTypeVal) = + updateStack(data, bytes.last, Right(t.op(data(bytes(1)), data(bytes(2))))) private val ensured = (b: Array[Byte], d: Seq[DataEntry]) => b.length == 4 && checkIndexes(b, d, Seq(1, 2)) override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(CompareType(f)).toOption) match { - case Some(t: CompareType.NumCompareTypeVal) if ensured(bytes, data) => numDiffer(bytes, data, t) - case Some(CompareType.Beq) if ensured(bytes, data) => bytesDiffer(bytes, data, _ == _) - case Some(CompareType.Bne) if ensured(bytes, data) => bytesDiffer(bytes, data, _ != _) + case Some(t: CompareType.NumCompareTypeVal) if ensured(bytes, data) => differ(bytes, data, t) + case Some(t: CompareType.BytesCompareTypeVal) if ensured(bytes, data) => differ(bytes, data, t) case _ => Left(ContractInvalidOPCData) } } From bdbaefd7840ad3a04cb0d90ecb5c253fa60a5595 Mon Sep 17 00:00:00 2001 From: zl730 Date: Wed, 14 Oct 2020 14:07:45 +0800 Subject: [PATCH 087/391] remove extra blank lines --- .../scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala index ca206996f..540ce5c2f 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CompareOpcDiff.scala @@ -12,8 +12,6 @@ import scala.util.{Left, Right, Try} object CompareOpcDiff extends OpcDiffer { - - case class NumComparator(int: (Int, Int) => Boolean, long: (Long, Long) => Boolean, bigInt: (BigInt, BigInt) => Boolean) val ge = NumComparator(_ >= _, _ >= _, _ >= _) From 0e257473b84b03f5955a4c1b20c7f4df122a42d9 Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 21 Oct 2020 11:02:18 +0800 Subject: [PATCH 088/391] add vswap contract template --- .../blockchain/contract/ContractVSwap.scala | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/scala/vsys/blockchain/contract/ContractVSwap.scala diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala new file mode 100644 index 000000000..d2f8ec2d7 --- /dev/null +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -0,0 +1,30 @@ +package vsys.blockchain.contract + +import com.google.common.primitives.Ints +import vsys.blockchain.state._ +import vsys.utils.serialization.Deser + +object ContractVSwap { + lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(), + Seq(), + Seq(), + Seq(), + Seq() + ).explicitGet() + + // State Var + + // State Map + + // Initialization Trigger + + // Deposit Trigger + + // WithDraw Trigger + + // Functions + + // Textual + +} \ No newline at end of file From 1ef070fac1f8af403c627aac97161e27fd80f8a9 Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 21 Oct 2020 11:25:46 +0800 Subject: [PATCH 089/391] add vswap state vars --- .../blockchain/contract/ContractVSwap.scala | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index d2f8ec2d7..6626f3374 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -1,19 +1,36 @@ package vsys.blockchain.contract import com.google.common.primitives.Ints +import vsys.blockchain.contract.ContractGen._ import vsys.blockchain.state._ import vsys.utils.serialization.Deser object ContractVSwap { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), - Seq(), - Seq(), - Seq(), - Seq(), - Seq() + Seq(), // Triggers + Seq(), // Functions + stateVarSeq, // StateVars + Seq(), // StateMaps + Seq() // Textual ).explicitGet() // State Var + val stateVarName = List("maker", "tokenAId", "tokenBId", "tokenLiquidityId", "swapStatus", "minimumLiquidity", + "tokenAReserved", "tokenBReserved", "totalSupply", "liquidityTokenLeft") + val makerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) + val tokenAIdStateVar: StateVar = StateVar(1.toByte, DataType.TokenId.id.toByte) + val tokeBIdStateVar: StateVar = StateVar(2.toByte, DataType.TokenId.id.toByte) + val tokenLiquidityIdStateVar: StateVar = StateVar(3.toByte, DataType.TokenId.id.toByte) + val swapStatusStateVar: StateVar = StateVar(4.toByte, DataType.Boolean.id.toByte) + val minimumLiquidityStateVar: StateVar = StateVar(5.toByte, DataType.Amount.id.toByte) + val tokenAReservedStateVar: StateVar = StateVar(6.toByte, DataType.Amount.id.toByte) + val tokenBReservedStateVar: StateVar = StateVar(7.toByte, DataType.Amount.id.toByte) + val totalSupplyStateVar: StateVar = StateVar(8.toByte, DataType.Amount.id.toByte) + val liquidityTokenLeftStateVar: StateVar = StateVar(9.toByte, DataType.Amount.id.toByte) + lazy val stateVarSeq = Seq(makerStateVar.arr, tokenAIdStateVar.arr, tokeBIdStateVar.arr, tokenLiquidityIdStateVar.arr, + swapStatusStateVar.arr, minimumLiquidityStateVar.arr, tokenAReservedStateVar.arr, + tokenBReservedStateVar.arr, totalSupplyStateVar.arr, liquidityTokenLeftStateVar.arr) + lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map From 0de1f671f008f78a3a8f43baa6bbade3226b1b28 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 22 Oct 2020 10:17:53 +0800 Subject: [PATCH 090/391] add vswap state map --- .../scala/vsys/blockchain/contract/ContractVSwap.scala | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 6626f3374..d652eb15f 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -10,7 +10,7 @@ object ContractVSwap { Seq(), // Triggers Seq(), // Functions stateVarSeq, // StateVars - Seq(), // StateMaps + stateMapSeq, // StateMaps Seq() // Textual ).explicitGet() @@ -33,6 +33,14 @@ object ContractVSwap { lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map + val stateMapTokenABalance = List("tokenABalance", "userAddress", "balance") + val stateMapTokenBBalance = List("tokenBBalance", "userAddress", "balance") + val stateMapLiquidityBalance = List("liquidityBalance", "userAddress", "balance") + val tokenABalanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val tokenBBalanceMap: StateMap = StateMap(1.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val liquidityBalanceMap: StateMap = StateMap(2.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + lazy val stateMapSeq = Seq(tokenABalanceMap.arr, tokenBBalanceMap.arr, liquidityBalanceMap.arr) + lazy val stateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapTokenABalance, stateMapTokenBBalance, stateMapLiquidityBalance)) // Initialization Trigger From b9cc6395e34c8dadd53472a3b2ce6daf4c11d603 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 22 Oct 2020 10:18:39 +0800 Subject: [PATCH 091/391] add supersede func --- .../vsys/blockchain/contract/ContractVSwap.scala | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index d652eb15f..534e96481 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -49,6 +49,19 @@ object ContractVSwap { // WithDraw Trigger // Functions + // Supersede + val supersedeId: Short = 0 + val supersedeIdWithoutSplit: Short = 0 + val supersedePara: Seq[String] = Seq("newOwner", + "maker") + val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val supersedeOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(makerStateVar.index, 1.toByte), + assertSigner ++ Array(1.toByte), + cdbvSet ++ Array(makerStateVar.index, 0.toByte)) + lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) + lazy val supersedeFuncWithoutSplit: Array[Byte] = getFunctionBytes(supersedeIdWithoutSplit, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) + val supersedeFuncBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) // Textual From 6642539bbe2fd563326e6773fdc418496a2449de Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 23 Oct 2020 00:13:49 +0800 Subject: [PATCH 092/391] add opcs to contract gen --- src/main/scala/vsys/blockchain/contract/ContractGen.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractGen.scala b/src/main/scala/vsys/blockchain/contract/ContractGen.scala index 44985d357..86114472d 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractGen.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractGen.scala @@ -25,6 +25,8 @@ object ContractGen { val cdbvMapSet = Array(3.toByte, 2.toByte) val cdbvMapValAdd = Array(3.toByte, 3.toByte) val cdbvMapValMinus = Array(3.toByte, 4.toByte) + val cdbvStateValAdd = Array(3.toByte, 5.toByte) + val cdbvStateValMinus = Array(3.toByte, 6.toByte) val cdbvrGet = Array(4.toByte, 1.toByte) val cdbvrMapGetOrDefault = Array(4.toByte, 2.toByte) @@ -44,7 +46,8 @@ object ContractGen { val returnValue = Array(9.toByte, 1.toByte) - val compareGreater = Array(10.toByte, 1.toByte) + val compareGreaterEqual = Array(10.toByte, 1.toByte) + val compareGreater = Array(10.toByte, 2.toByte) val basicAdd = Array(11.toByte, 1.toByte) val basicMinus = Array(11.toByte, 2.toByte) @@ -54,6 +57,8 @@ object ContractGen { val basicMax = Array(11.toByte, 6.toByte) val basicConcat = Array(11.toByte, 7.toByte) val basicConstantGet = Array(11.toByte, 8.toByte) + val basicSqrtBigint = Array(11.toByte, 9.toByte) + val basicConvert = Array(11.toByte, 10.toByte) sealed case class StateVar(index: Byte, dataType: Byte) { lazy val arr: Array[Byte] = Array(index, dataType) From 6c0db5abf3673c671f373b025a04321b754c730f Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 23 Oct 2020 00:14:56 +0800 Subject: [PATCH 093/391] fix compare greater to greater equal --- .../scala/vsys/blockchain/contract/ContractLock.scala | 4 ++-- .../blockchain/contract/ContractPaymentChannel.scala | 10 +++++----- .../vsys/blockchain/contract/ContractGenHelper.scala | 2 +- .../vsys/blockchain/contract/lock/LockFunction.scala | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractLock.scala b/src/main/scala/vsys/blockchain/contract/ContractLock.scala index 14d19678b..bab720fa9 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractLock.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractLock.scala @@ -64,7 +64,7 @@ object ContractLock { assertEqual ++ Array(2.toByte, 3.toByte), loadTimestamp ++ Array(4.toByte), cdbvrMapGetOrDefault ++ Array(lockTimeMap.index, 0.toByte, 5.toByte), - compareGreater ++ Array(4.toByte, 5.toByte, 6.toByte), + compareGreaterEqual ++ Array(4.toByte, 5.toByte, 6.toByte), assertTrue ++ Array(6.toByte), cdbvMapValMinus ++ Array(balanceMap.index, 0.toByte, 1.toByte) ) @@ -79,7 +79,7 @@ object ContractLock { val lockFunctionOpcs: Seq[Array[Byte]] = Seq( loadCaller ++ Array(1.toByte), cdbvrMapGetOrDefault ++ Array(lockTimeMap.index, 1.toByte, 2.toByte), - compareGreater ++ Array(0.toByte, 2.toByte, 3.toByte), + compareGreaterEqual ++ Array(0.toByte, 2.toByte, 3.toByte), assertTrue ++ Array(3.toByte), cdbvMapSet ++ Array(lockTimeMap.index, 1.toByte, 0.toByte) ) diff --git a/src/main/scala/vsys/blockchain/contract/ContractPaymentChannel.scala b/src/main/scala/vsys/blockchain/contract/ContractPaymentChannel.scala index 3a60f2c59..288939e93 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractPaymentChannel.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractPaymentChannel.scala @@ -117,7 +117,7 @@ object ContractPaymentChannel { cdbvrMapGet ++ Array(channelStatusMap.index, 0.toByte, 3.toByte), assertTrue ++ Array(3.toByte), cdbvrMapGet ++ Array(channelExpirationTimeMap.index, 0.toByte, 4.toByte), - compareGreater ++ Array(1.toByte, 4.toByte, 5.toByte), + compareGreaterEqual ++ Array(1.toByte, 4.toByte, 5.toByte), assertTrue ++ Array(5.toByte), cdbvMapSet ++ Array(channelExpirationTimeMap.index, 0.toByte, 1.toByte) ) @@ -169,7 +169,7 @@ object ContractPaymentChannel { assertCaller ++ Array(1.toByte), loadTimestamp ++ Array(2.toByte), cdbvrMapGet ++ Array(channelExpirationTimeMap.index, 0.toByte, 3.toByte), - compareGreater ++ Array(2.toByte, 3.toByte, 4.toByte), + compareGreaterEqual ++ Array(2.toByte, 3.toByte, 4.toByte), assertTrue ++ Array(4.toByte), cdbvrMapGetOrDefault ++ Array(accumulatedLoadMap.index, 0.toByte, 5.toByte), cdbvrMapGetOrDefault ++ Array(accumulatedPaymentMap.index, 0.toByte, 6.toByte), @@ -191,16 +191,16 @@ object ContractPaymentChannel { assertCaller ++ Array(3.toByte), loadTimestamp ++ Array(4.toByte), cdbvrMapGet ++ Array(channelExpirationTimeMap.index, 0.toByte, 5.toByte), - compareGreater ++ Array(5.toByte, 4.toByte, 6.toByte), + compareGreaterEqual ++ Array(5.toByte, 4.toByte, 6.toByte), assertTrue ++ Array(6.toByte), cdbvrMapGet ++ Array(channelCreatorPublicKeyMap.index, 0.toByte, 7.toByte), basicConcat ++ Array(0.toByte, 1.toByte, 8.toByte), assertSig ++ Array(8.toByte, 2.toByte, 7.toByte), cdbvrMapGetOrDefault ++ Array(accumulatedPaymentMap.index, 0.toByte, 9.toByte), - compareGreater ++ Array(1.toByte, 9.toByte, 10.toByte), + compareGreaterEqual ++ Array(1.toByte, 9.toByte, 10.toByte), assertTrue ++ Array(10.toByte), cdbvrMapGetOrDefault ++ Array(accumulatedLoadMap.index, 0.toByte, 11.toByte), - compareGreater ++ Array(11.toByte, 1.toByte, 12.toByte), + compareGreaterEqual ++ Array(11.toByte, 1.toByte, 12.toByte), assertTrue ++ Array(12.toByte), basicMinus ++ Array(1.toByte, 9.toByte, 13.toByte), cdbvMapValAdd ++ Array(accumulatedPaymentMap.index, 0.toByte, 13.toByte), diff --git a/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala b/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala index 28ae19d7d..913de29eb 100644 --- a/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala +++ b/src/test/scala/vsys/blockchain/contract/ContractGenHelper.scala @@ -42,7 +42,7 @@ object ContractGenHelper extends TransactionGen { val returnValue = Array(9.toByte, 1.toByte) - val compareGreater = Array(10.toByte, 1.toByte) + val compareGreaterEqual = Array(10.toByte, 1.toByte) val ENOUGH_AMT: Long = Long.MaxValue / 3 diff --git a/src/test/scala/vsys/blockchain/contract/lock/LockFunction.scala b/src/test/scala/vsys/blockchain/contract/lock/LockFunction.scala index ceef71bbd..716f26258 100644 --- a/src/test/scala/vsys/blockchain/contract/lock/LockFunction.scala +++ b/src/test/scala/vsys/blockchain/contract/lock/LockFunction.scala @@ -16,7 +16,7 @@ trait LockFunction { val lockFunctionOpcs: Seq[Array[Byte]] = Seq( loadCaller ++ Array(1.toByte), cdbvrMapGetOrDefault ++ Array(lockTimeMap.index, 1.toByte, 2.toByte), - compareGreater ++ Array(0.toByte, 2.toByte, 3.toByte), + compareGreaterEqual ++ Array(0.toByte, 2.toByte, 3.toByte), assertTrue ++ Array(3.toByte), cdbvMapSet ++ Array(lockTimeMap.index, 1.toByte, 0.toByte) ) @@ -24,7 +24,7 @@ trait LockFunction { val lockWrongFunctionOpcs: Seq[Array[Byte]] = Seq( Array(2.toByte, 0.toByte) ++ Array(1.toByte), cdbvrMapGetOrDefault ++ Array(lockTimeMap.index, 1.toByte, 2.toByte), - compareGreater ++ Array(0.toByte, 2.toByte, 3.toByte), + compareGreaterEqual ++ Array(0.toByte, 2.toByte, 3.toByte), assertTrue ++ Array(3.toByte), cdbvMapSet ++ Array(lockTimeMap.index, 1.toByte, 0.toByte) ) From eae346e5f1dead24e9c53407b3e92f3800b2d26e Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 23 Oct 2020 00:16:30 +0800 Subject: [PATCH 094/391] add set swap function --- .../blockchain/contract/ContractVSwap.scala | 54 +++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 534e96481..a5cf6840e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -1,6 +1,6 @@ package vsys.blockchain.contract -import com.google.common.primitives.Ints +import com.google.common.primitives.{Ints, Longs} import vsys.blockchain.contract.ContractGen._ import vsys.blockchain.state._ import vsys.utils.serialization.Deser @@ -51,18 +51,64 @@ object ContractVSwap { // Functions // Supersede val supersedeId: Short = 0 - val supersedeIdWithoutSplit: Short = 0 val supersedePara: Seq[String] = Seq("newOwner", - "maker") + "maker") val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte) val supersedeOpcs: Seq[Array[Byte]] = Seq( cdbvrGet ++ Array(makerStateVar.index, 1.toByte), assertSigner ++ Array(1.toByte), cdbvSet ++ Array(makerStateVar.index, 0.toByte)) lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) - lazy val supersedeFuncWithoutSplit: Array[Byte] = getFunctionBytes(supersedeIdWithoutSplit, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) val supersedeFuncBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) + // Set Swap + val setSwapId: Short = 1 + val setSwapPara: Seq[String] = Seq("amountADesired", "amountBDesired", + "maker", "swapStatus", "valueFalse", "amountZero", "isValidAmountADesired", "isValidAmountBDesired", + "bigIntType", "amountADesiredBigInt", "amountBDesiredBigInt", "valueK", "initLiquidityBigInt", + "amountType", "initLiquidity", "minimumLiquidity", "isValidInitLiquidity", "liquidity", + "maxLiquidity", "isValidLiquidity", "liquidityLeft", "valueTrue") + val setSwapDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Amount.id.toByte) + val setSwapFunctionOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(makerStateVar.index, 2.toByte), + assertCaller ++ Array(2.toByte), + cdbvrGet ++ Array(swapStatusStateVar.index, 3.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(4.toByte), + assertEqual ++ Array(3.toByte, 4.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(5.toByte), + compareGreater ++ Array(0.toByte, 5.toByte, 6.toByte), + assertTrue ++ Array(6.toByte), + compareGreater ++ Array(1.toByte, 5.toByte, 7.toByte), + assertTrue ++ Array(7.toByte), + cdbvMapValMinus ++ Array(tokenABalanceMap.index, 2.toByte, 0.toByte), + cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 2.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(8.toByte), + basicConvert ++ Array(0.toByte, 8.toByte, 9.toByte), + basicConvert ++ Array(1.toByte, 8.toByte, 10.toByte), + basicMultiply ++ Array(9.toByte, 10.toByte, 11.toByte), + basicSqrtBigint ++ Array(11.toByte, 12.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(13.toByte), + basicConvert ++ Array(12.toByte, 13.toByte, 14.toByte), + cdbvrGet ++ Array(minimumLiquidityStateVar.index, 15.toByte), + compareGreater ++ Array(14.toByte, 15.toByte, 16.toByte), + assertTrue ++ Array(16.toByte), + basicMinus ++ Array(14.toByte, 15.toByte, 17.toByte), + cdbvrMapGet ++ Array(liquidityBalanceMap.index, 2.toByte, 18.toByte), + compareGreater ++ Array(18.toByte, 14.toByte, 19.toByte), + assertTrue ++ Array(19.toByte), + cdbvMapValMinus ++ Array(liquidityBalanceMap.index, 2.toByte, 18.toByte), + cdbvMapValAdd ++ Array(liquidityBalanceMap.index, 2.toByte, 17.toByte), + basicMinus ++ Array(18.toByte, 14.toByte, 19.toByte), + cdbvStateValAdd ++ Array(liquidityTokenLeftStateVar.index, 19.toByte), + cdbvStateValAdd ++ Array(totalSupplyStateVar.index, 14.toByte), + cdbvStateValAdd ++ Array(tokenAReservedStateVar.index, 0.toByte), + cdbvStateValAdd ++ Array(tokenBReservedStateVar.index, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(20.toByte), + cdbvSet ++ Array(swapStatusStateVar.index, 20.toByte) + ) + lazy val setSwapFunc: Array[Byte] = getFunctionBytes(setSwapId, publicFuncType, nonReturnType, setSwapDataType, setSwapFunctionOpcs) + val setSwapTextualBytes: Array[Byte] = textualFunc("setSwap", Seq(), setSwapPara) + // Textual } \ No newline at end of file From dfa55799de85e96375c8fbf0642662788b962fab Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 23 Oct 2020 09:32:53 +0800 Subject: [PATCH 095/391] add liquidity func --- .../blockchain/contract/ContractGen.scala | 1 + .../blockchain/contract/ContractVSwap.scala | 71 ++++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractGen.scala b/src/main/scala/vsys/blockchain/contract/ContractGen.scala index 86114472d..a667ed10b 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractGen.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractGen.scala @@ -31,6 +31,7 @@ object ContractGen { val cdbvrGet = Array(4.toByte, 1.toByte) val cdbvrMapGetOrDefault = Array(4.toByte, 2.toByte) val cdbvrMapGet = Array(4.toByte, 3.toByte) + val cdbvrGetOrDefault = Array(4.toByte, 4.toByte) val tdbNewToken = Array(5.toByte, 1.toByte) val tdbSplit = Array(5.toByte, 2.toByte) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index a5cf6840e..59f53cdb3 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -63,8 +63,8 @@ object ContractVSwap { // Set Swap val setSwapId: Short = 1 - val setSwapPara: Seq[String] = Seq("amountADesired", "amountBDesired", - "maker", "swapStatus", "valueFalse", "amountZero", "isValidAmountADesired", "isValidAmountBDesired", + val setSwapPara: Seq[String] = Seq("amountADesired", "amountBDesired") ++ + Seq("maker", "swapStatus", "valueFalse", "amountZero", "isValidAmountADesired", "isValidAmountBDesired", "bigIntType", "amountADesiredBigInt", "amountBDesiredBigInt", "valueK", "initLiquidityBigInt", "amountType", "initLiquidity", "minimumLiquidity", "isValidInitLiquidity", "liquidity", "maxLiquidity", "isValidLiquidity", "liquidityLeft", "valueTrue") @@ -109,6 +109,73 @@ object ContractVSwap { lazy val setSwapFunc: Array[Byte] = getFunctionBytes(setSwapId, publicFuncType, nonReturnType, setSwapDataType, setSwapFunctionOpcs) val setSwapTextualBytes: Array[Byte] = textualFunc("setSwap", Seq(), setSwapPara) + // Add Liquidity + val addLiquidityId: Short = 2 + val addLiquidityPara: Seq[String] = Seq("amountADesired", "amountBDesired", "amountAMin", "amountBMin", "deadline") ++ + Seq("caller", "swapStatus", "currentTime", "isValidTime", "amountZero", + "reserveA", "isValidReserveA", "reserveB", "isValidReserveB", + "bigIntType", "reserveABigInt", "reserveBBigInt", "amountADesiredBigInt", "amountBDesiredBigInt", + "mulA", "amountBGet", "mulB", "amountAGet", "amountType", "amountABigInt", "amountA", "isValidAmountA", + "amountBBigInt", "amountB", "isValidAmountB", "totalSupply", "totalSupplyBigInt", + "mulSupplyA", "mulSupplyB", "liquidityABigInt", "liquidityBBigInt", "liquidityBigInt", + "liquidity", "liquidityLeft", "isValidLiquidity") + val addLiquidityDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Amount.id.toByte, + DataType.Amount.id.toByte, DataType.Amount.id.toByte, DataType.Timestamp.id.toByte) + val addLiquidityFunctionOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(5.toByte), + cdbvrGet ++ Array(swapStatusStateVar.index, 6.toByte), + assertTrue ++ Array(6.toByte), + loadTimestamp ++ Array(7.toByte), + compareGreaterEqual ++ Array(4.toByte, 7.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(9.toByte), + cdbvrGetOrDefault ++ Array(tokenAReservedStateVar.index, 10.toByte), + compareGreater ++ Array(10.toByte, 9.toByte, 11.toByte), + assertTrue ++ Array(11.toByte), + cdbvrGetOrDefault ++ Array(tokenBReservedStateVar.index, 12.toByte), + compareGreater ++ Array(12.toByte, 9.toByte, 13.toByte), + assertTrue ++ Array(13.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(14.toByte), + basicConvert ++ Array(10.toByte, 14.toByte, 15.toByte), + basicConvert ++ Array(12.toByte, 14.toByte, 16.toByte), + basicConvert ++ Array(0.toByte, 14.toByte, 17.toByte), + basicConvert ++ Array(1.toByte, 14.toByte, 18.toByte), + basicMultiply ++ Array(17.toByte, 16.toByte, 19.toByte), + basicDivide ++ Array(19.toByte, 15.toByte, 20.toByte), + basicMultiply ++ Array(18.toByte, 15.toByte, 21.toByte), + basicDivide ++ Array(21.toByte, 16.toByte, 22.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(23.toByte), + basicMin ++ Array(20.toByte, 17.toByte, 24.toByte), + basicConvert ++ Array(24.toByte, 23.toByte, 25.toByte), + compareGreaterEqual ++ Array(25.toByte, 2.toByte, 26.toByte), + assertTrue ++ Array(26.toByte), + basicMin ++ Array(22.toByte, 18.toByte, 27.toByte), + basicConvert ++ Array(27.toByte, 23.toByte, 28.toByte), + compareGreaterEqual ++ Array(28.toByte, 3.toByte, 29.toByte), + assertTrue ++ Array(29.toByte), + cdbvMapValMinus ++ Array(tokenABalanceMap.index, 5.toByte, 25.toByte), + cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 5.toByte, 28.toByte), + cdbvrGetOrDefault ++ Array(totalSupplyStateVar.index, 30.toByte), + basicConvert ++ Array(30.toByte, 14.toByte, 31.toByte), + basicMultiply ++ Array(24.toByte, 31.toByte, 32.toByte), + basicMultiply ++ Array(27.toByte, 31.toByte, 33.toByte), + basicDivide ++ Array(32.toByte, 15.toByte, 34.toByte), + basicDivide ++ Array(33.toByte, 16.toByte, 35.toByte), + basicMin ++ Array(34.toByte, 35.toByte, 36.toByte), + basicConvert ++ Array(36.toByte, 23.toByte, 37.toByte), + cdbvrGetOrDefault ++ Array(liquidityTokenLeftStateVar.index, 38.toByte), + compareGreaterEqual ++ Array(38.toByte, 37.toByte, 39.toByte), + assertTrue ++ Array(39.toByte), + cdbvStateValMinus ++ Array(liquidityTokenLeftStateVar.index, 37.toByte), + cdbvStateValAdd ++ Array(totalSupplyStateVar.index, 37.toByte), + cdbvStateValAdd ++ Array(tokenAReservedStateVar.index, 25.toByte), + cdbvStateValAdd ++ Array(tokenBReservedStateVar.index, 28.toByte), + cdbvMapValAdd ++ Array(liquidityBalanceMap.index, 5.toByte, 37.toByte) + ) + lazy val addLiquidityFunc: Array[Byte] = getFunctionBytes(addLiquidityId, publicFuncType, nonReturnType, + addLiquidityDataType, addLiquidityFunctionOpcs) + val addLiquidityTextualBytes: Array[Byte] = textualFunc("addLiquidity", Seq(), addLiquidityPara) + // Textual } \ No newline at end of file From f4b7e202f60dd12ea0c432a36cd42112558a8a95 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 23 Oct 2020 10:06:19 +0800 Subject: [PATCH 096/391] remove liquidity func --- .../blockchain/contract/ContractVSwap.scala | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 59f53cdb3..e474bc636 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -176,6 +176,57 @@ object ContractVSwap { addLiquidityDataType, addLiquidityFunctionOpcs) val addLiquidityTextualBytes: Array[Byte] = textualFunc("addLiquidity", Seq(), addLiquidityPara) + // Remove Liquidity + val removeLiquidityId: Short = 2 + val removeLiquidityPara: Seq[String] = Seq("liquidity", "amountAMin", "amountBMin", "deadline") ++ + Seq("caller", "swapStatus", "currentTime", "isValidTime", "reserveA", "reserveB", + "bigIntType", "liquidityBigInt", "reserveABigInt", "reserveBBigInt", + "totalSupply", "amountZero", "isValidTotalSupply", "totalSupplyBigInt", + "mulA", "amountABigInt", "mulB", "amountBBigInt", "amountType", "amountA", "amountB", + "isValidAmountA", "isValidAmountB") + val removeLiquidityDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Amount.id.toByte, + DataType.Amount.id.toByte, DataType.Timestamp.id.toByte) + val removeLiquidityFunctionOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(4.toByte), + cdbvrGet ++ Array(swapStatusStateVar.index, 5.toByte), + assertTrue ++ Array(5.toByte), + loadTimestamp ++ Array(6.toByte), + compareGreaterEqual ++ Array(3.toByte, 6.toByte, 7.toByte), + assertTrue ++ Array(7.toByte), + cdbvMapValMinus ++ Array(liquidityBalanceMap.index, 4.toByte, 0.toByte), + cdbvrGetOrDefault ++ Array(tokenAReservedStateVar.index, 8.toByte), + cdbvrGetOrDefault ++ Array(tokenBReservedStateVar.index, 9.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(10.toByte), + basicConvert ++ Array(0.toByte, 10.toByte, 11.toByte), + basicConvert ++ Array(8.toByte, 10.toByte, 12.toByte), + basicConvert ++ Array(9.toByte, 10.toByte, 13.toByte), + cdbvrGetOrDefault ++ Array(totalSupplyStateVar.index, 14.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(15.toByte), + compareGreater ++ Array(14.toByte, 15.toByte, 16.toByte), + assertTrue ++ Array(16.toByte), + basicConvert ++ Array(14.toByte, 10.toByte, 17.toByte), + basicMultiply ++ Array(11.toByte, 12.toByte, 18.toByte), + basicDivide ++ Array(18.toByte, 17.toByte, 19.toByte), + basicMultiply ++ Array(11.toByte, 13.toByte, 20.toByte), + basicDivide ++ Array(20.toByte, 17.toByte, 21.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(22.toByte), + basicConvert ++ Array(19.toByte, 22.toByte, 23.toByte), + basicConvert ++ Array(21.toByte, 22.toByte, 24.toByte), + compareGreaterEqual ++ Array(23.toByte, 1.toByte, 25.toByte), + assertTrue ++ Array(25.toByte), + compareGreaterEqual ++ Array(24.toByte, 2.toByte, 26.toByte), + assertTrue ++ Array(26.toByte), + cdbvStateValMinus ++ Array(totalSupplyStateVar.index, 0.toByte), + cdbvStateValMinus ++ Array(tokenAReservedStateVar.index, 23.toByte), + cdbvStateValMinus ++ Array(tokenBReservedStateVar.index, 24.toByte), + cdbvMapValAdd ++ Array(tokenABalanceMap.index, 4.toByte, 23.toByte), + cdbvMapValAdd ++ Array(tokenBBalanceMap.index, 4.toByte, 24.toByte), + cdbvStateValAdd ++ Array(liquidityTokenLeftStateVar.index, 0.toByte) + ) + lazy val removeLiquidityFunc: Array[Byte] = getFunctionBytes(removeLiquidityId, publicFuncType, nonReturnType, + removeLiquidityDataType, removeLiquidityFunctionOpcs) + val removeLiquidityTextualBytes: Array[Byte] = textualFunc("removeLiquidity", Seq(), removeLiquidityPara) + // Textual } \ No newline at end of file From 6f7eb6cbb761001043531fe66073a8873c05d43d Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 23 Oct 2020 10:11:59 +0800 Subject: [PATCH 097/391] add common swap code --- .../vsys/blockchain/contract/ContractVSwap.scala | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index e474bc636..b6addee7e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -227,6 +227,18 @@ object ContractVSwap { removeLiquidityDataType, removeLiquidityFunctionOpcs) val removeLiquidityTextualBytes: Array[Byte] = textualFunc("removeLiquidity", Seq(), removeLiquidityPara) + // Common Swap Code + val commonSwapPara: Seq[String] = Seq("caller", "swapStatus", "currentTime", "isValidTime") + val swapDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Amount.id.toByte, DataType.Timestamp.id.toByte) + val commonSwapFunctionOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(3.toByte), + cdbvrGet ++ Array(swapStatusStateVar.index, 4.toByte), + assertTrue ++ Array(4.toByte), + loadTimestamp ++ Array(5.toByte), + compareGreaterEqual ++ Array(2.toByte, 5.toByte, 6.toByte), + assertTrue ++ Array(6.toByte), + ) + // Textual } \ No newline at end of file From 5f4d2442840cbf61b81f67806d50575c500fc3e6 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 27 Oct 2020 10:37:23 +0800 Subject: [PATCH 098/391] add swap token for exact base token func --- .../blockchain/contract/ContractVSwap.scala | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index b6addee7e..57e406a85 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -239,6 +239,59 @@ object ContractVSwap { assertTrue ++ Array(6.toByte), ) + val swapTokenForExactBaseTokenId: Short = 3 + val swapTokenForExactBaseTokenPara: Seq[String] = Seq("amountOut", "amountInMax", "deadline") ++ + commonSwapPara ++ + Seq("amountZero", "isValidAmountOut", "reserveA", "reserveB", + "bigIntType", "amountOutBigInt", "reserveABigInt", "reserveBBigInt", + "value1000", "mulValue", "numerator", "value997", "subValue", "denominator", + "valueOne", "amountInBigIntPre", "amountInBigInt", "amountType", + "amountIn", "isValidAmountIn", "updatedReserveA", "amountInWithOutFee", + "updatedReserveB", "updatedK", "KValue", "valueSquare", "oldK", "isValidUpdatedK" + ) + val swapTokenForExactBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ Seq( + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(7.toByte), + compareGreater ++ Array(0.toByte, 7.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + cdbvrGetOrDefault ++ Array(tokenAReservedStateVar.index, 9.toByte), + cdbvrGetOrDefault ++ Array(tokenBReservedStateVar.index, 10.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(11.toByte), + basicConvert ++ Array(0.toByte, 11.toByte, 12.toByte), + basicConvert ++ Array(9.toByte, 11.toByte, 13.toByte), + basicConvert ++ Array(10.toByte, 11.toByte, 14.toByte), + basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), + basicMultiply ++ Array(14.toByte, 15.toByte, 16.toByte), + basicMultiply ++ Array(16.toByte, 12.toByte, 17.toByte), + basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(18.toByte), + basicMinus ++ Array(13.toByte, 12.toByte, 19.toByte), + basicMultiply ++ Array(19.toByte, 18.toByte, 20.toByte), + basicConstantGet ++ DataEntry(BigInt(1).toByteArray, DataType.BigInteger).bytes ++ Array(21.toByte), + basicDivide ++ Array(17.toByte, 20.toByte, 22.toByte), + basicAdd ++ Array(22.toByte, 21.toByte, 23.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(24.toByte), + basicConvert ++ Array(23.toByte, 24.toByte, 25.toByte), + compareGreaterEqual ++ Array(25.toByte, 1.toByte, 26.toByte), + assertTrue ++ Array(26.toByte), + basicMultiply ++ Array(19.toByte, 15.toByte, 27.toByte), + basicMultiply ++ Array(23.toByte, 18.toByte, 28.toByte), + basicAdd ++ Array(16.toByte, 28.toByte, 29.toByte), + basicMultiply ++ Array(27.toByte, 29.toByte, 30.toByte), + basicMultiply ++ Array(13.toByte, 14.toByte, 31.toByte), + basicMultiply ++ Array(15.toByte, 15.toByte, 32.toByte), + basicMultiply ++ Array(31.toByte, 32.toByte, 33.toByte), + compareGreaterEqual ++ Array(30.toByte, 33.toByte, 34.toByte), + assertTrue ++ Array(34.toByte), + // minus may put directly after load reserved token value A and B + cdbvStateValMinus ++ Array(tokenAReservedStateVar.index, 0.toByte), + cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 3.toByte, 25.toByte), + cdbvStateValAdd ++ Array(tokenBReservedStateVar.index, 25.toByte), + cdbvMapValAdd ++ Array(tokenBBalanceMap.index, 3.toByte, 0.toByte) + ) + lazy val swapTokenForExactBaseTokenFunc: Array[Byte] = getFunctionBytes(swapTokenForExactBaseTokenId, publicFuncType, nonReturnType, + swapDataType, swapTokenForExactBaseTokenFunctionOpcs) + val swapTokenForExactBaseTokenTextualBytes: Array[Byte] = textualFunc("swapTokenForExactBaseToken", Seq(), swapTokenForExactBaseTokenPara) + + // Textual } \ No newline at end of file From 5183f13bf9ff74f37f45e1330d6537572da0309a Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 27 Oct 2020 11:16:57 +0800 Subject: [PATCH 099/391] add swap exact token for base token func --- .../blockchain/contract/ContractVSwap.scala | 56 +++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 57e406a85..7ce4c3b70 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -247,8 +247,7 @@ object ContractVSwap { "value1000", "mulValue", "numerator", "value997", "subValue", "denominator", "valueOne", "amountInBigIntPre", "amountInBigInt", "amountType", "amountIn", "isValidAmountIn", "updatedReserveA", "amountInWithOutFee", - "updatedReserveB", "updatedK", "KValue", "valueSquare", "oldK", "isValidUpdatedK" - ) + "updatedReserveB", "updatedK", "KValue", "valueSquare", "oldK", "isValidUpdatedK") val swapTokenForExactBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ Seq( basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(7.toByte), compareGreater ++ Array(0.toByte, 7.toByte, 8.toByte), @@ -270,7 +269,7 @@ object ContractVSwap { basicAdd ++ Array(22.toByte, 21.toByte, 23.toByte), basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(24.toByte), basicConvert ++ Array(23.toByte, 24.toByte, 25.toByte), - compareGreaterEqual ++ Array(25.toByte, 1.toByte, 26.toByte), + compareGreaterEqual ++ Array(1.toByte, 25.toByte, 26.toByte), assertTrue ++ Array(26.toByte), basicMultiply ++ Array(19.toByte, 15.toByte, 27.toByte), basicMultiply ++ Array(23.toByte, 18.toByte, 28.toByte), @@ -285,13 +284,60 @@ object ContractVSwap { cdbvStateValMinus ++ Array(tokenAReservedStateVar.index, 0.toByte), cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 3.toByte, 25.toByte), cdbvStateValAdd ++ Array(tokenBReservedStateVar.index, 25.toByte), - cdbvMapValAdd ++ Array(tokenBBalanceMap.index, 3.toByte, 0.toByte) + cdbvMapValAdd ++ Array(tokenABalanceMap.index, 3.toByte, 0.toByte) ) lazy val swapTokenForExactBaseTokenFunc: Array[Byte] = getFunctionBytes(swapTokenForExactBaseTokenId, publicFuncType, nonReturnType, swapDataType, swapTokenForExactBaseTokenFunctionOpcs) val swapTokenForExactBaseTokenTextualBytes: Array[Byte] = textualFunc("swapTokenForExactBaseToken", Seq(), swapTokenForExactBaseTokenPara) - + val swapExactTokenForBaseTokenId: Short = 4 + val swapExactTokenForBaseTokenPara: Seq[String] = Seq("amountOutMin", "amountIn", "deadline") ++ + commonSwapPara ++ + Seq("amountZero", "isValidAmountIn", "reserveA", "reserveB", + "bigIntType", "amountInBigInt", "reserveABigInt", "reserveBBigInt", + "value997", "amountInWithOutFee", "value1000", "mulValue", + "numerator", "denominator", "amountOutBigInt", "amountType", "amountOut", + "isValidAmountOut", "subValue", "updatedReserveA", "updatedReserveB", + "updatedK", "KValue", "valueSquare","oldK", "isValidUpdatedK") + val swapExactTokenForBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ Seq( + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(7.toByte), + compareGreater ++ Array(1.toByte, 7.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + cdbvrGetOrDefault ++ Array(tokenAReservedStateVar.index, 9.toByte), + cdbvrGetOrDefault ++ Array(tokenBReservedStateVar.index, 10.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(11.toByte), + basicConvert ++ Array(1.toByte, 11.toByte, 12.toByte), + basicConvert ++ Array(9.toByte, 11.toByte, 13.toByte), + basicConvert ++ Array(10.toByte, 11.toByte, 14.toByte), + basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), + basicMultiply ++ Array(12.toByte, 15.toByte, 16.toByte), + basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(17.toByte), + basicMultiply ++ Array(14.toByte, 17.toByte, 18.toByte), + basicMultiply ++ Array(13.toByte, 16.toByte, 19.toByte), + basicAdd ++ Array(18.toByte, 16.toByte, 20.toByte), + basicDivide ++ Array(19.toByte, 20.toByte, 21.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(22.toByte), + basicConvert ++ Array(21.toByte, 22.toByte, 23.toByte), + compareGreaterEqual ++ Array(23.toByte, 0.toByte, 24.toByte), + assertTrue ++ Array(24.toByte), + basicMinus ++ Array(13.toByte, 21.toByte, 25.toByte), + basicMultiply ++ Array(25.toByte, 17.toByte, 26.toByte), + basicAdd ++ Array(18.toByte, 16.toByte, 27.toByte), + basicMultiply ++ Array(26.toByte, 27.toByte, 28.toByte), + basicMultiply ++ Array(13.toByte, 14.toByte, 29.toByte), + basicMultiply ++ Array(17.toByte, 17.toByte, 30.toByte), + basicMultiply ++ Array(29.toByte, 30.toByte, 31.toByte), + compareGreaterEqual ++ Array(28.toByte, 31.toByte, 32.toByte), + assertTrue ++ Array(32.toByte), + cdbvStateValMinus ++ Array(tokenAReservedStateVar.index, 23.toByte), + cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 3.toByte, 1.toByte), + cdbvStateValAdd ++ Array(tokenBReservedStateVar.index, 1.toByte), + cdbvMapValAdd ++ Array(tokenABalanceMap.index, 3.toByte, 23.toByte) + ) + lazy val swapExactTokenForBaseTokenFunc: Array[Byte] = getFunctionBytes(swapExactTokenForBaseTokenId, publicFuncType, nonReturnType, + swapDataType, swapExactTokenForBaseTokenFunctionOpcs) + val swapExactTokenForBaseTokenTextualBytes: Array[Byte] = textualFunc("swapExactTokenForBaseToken", Seq(), swapExactTokenForBaseTokenPara) + // Textual } \ No newline at end of file From f6c6c813d17bc7357b840de8d4c94b070e6dbdcc Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 27 Oct 2020 14:18:02 +0800 Subject: [PATCH 100/391] add common opcs funcs --- .../blockchain/contract/ContractVSwap.scala | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 7ce4c3b70..8e450eb8e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -239,6 +239,32 @@ object ContractVSwap { assertTrue ++ Array(6.toByte), ) + private def commonSwapLoaded(checkIndex: Byte): Seq[Array[Byte]] = { + Seq( + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(7.toByte), + compareGreater ++ Array(checkIndex, 7.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + cdbvrGetOrDefault ++ Array(tokenAReservedStateVar.index, 9.toByte), + cdbvrGetOrDefault ++ Array(tokenBReservedStateVar.index, 10.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(11.toByte), + basicConvert ++ Array(checkIndex, 11.toByte, 12.toByte), + basicConvert ++ Array(9.toByte, 11.toByte, 13.toByte), + basicConvert ++ Array(10.toByte, 11.toByte, 14.toByte), + ) + } + + private def swapKValueCheck(updatedReserveA: Byte, updatedReserveB: Byte, value1000: Byte, + reservedABigInt: Byte, reservedBBigInt: Byte, updateK: Byte): Seq[Array[Byte]] = { + Seq( + basicMultiply ++ Array(updatedReserveA, updatedReserveA, updateK), + basicMultiply ++ Array(reservedABigInt, reservedBBigInt, (updateK + 1).toByte), + basicMultiply ++ Array(value1000, value1000, (updateK + 2).toByte), + basicMultiply ++ Array((updateK + 1).toByte, (updateK + 1).toByte, (updateK + 3).toByte), + compareGreaterEqual ++ Array(updateK, (updateK + 3).toByte, (updateK + 4).toByte), + assertTrue ++ Array((updateK + 4).toByte), + ) + } + val swapTokenForExactBaseTokenId: Short = 3 val swapTokenForExactBaseTokenPara: Seq[String] = Seq("amountOut", "amountInMax", "deadline") ++ commonSwapPara ++ From 9e7b821a1adb58a2a78b72f790ad8290f7a7367b Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 28 Oct 2020 10:16:19 +0800 Subject: [PATCH 101/391] simplify the code --- .../blockchain/contract/ContractVSwap.scala | 40 +++---------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 8e450eb8e..f99fee927 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -274,16 +274,7 @@ object ContractVSwap { "valueOne", "amountInBigIntPre", "amountInBigInt", "amountType", "amountIn", "isValidAmountIn", "updatedReserveA", "amountInWithOutFee", "updatedReserveB", "updatedK", "KValue", "valueSquare", "oldK", "isValidUpdatedK") - val swapTokenForExactBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ Seq( - basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(7.toByte), - compareGreater ++ Array(0.toByte, 7.toByte, 8.toByte), - assertTrue ++ Array(8.toByte), - cdbvrGetOrDefault ++ Array(tokenAReservedStateVar.index, 9.toByte), - cdbvrGetOrDefault ++ Array(tokenBReservedStateVar.index, 10.toByte), - basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(11.toByte), - basicConvert ++ Array(0.toByte, 11.toByte, 12.toByte), - basicConvert ++ Array(9.toByte, 11.toByte, 13.toByte), - basicConvert ++ Array(10.toByte, 11.toByte, 14.toByte), + val swapTokenForExactBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ commonSwapLoaded(0.toByte) ++ Seq( basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), basicMultiply ++ Array(14.toByte, 15.toByte, 16.toByte), basicMultiply ++ Array(16.toByte, 12.toByte, 17.toByte), @@ -299,13 +290,8 @@ object ContractVSwap { assertTrue ++ Array(26.toByte), basicMultiply ++ Array(19.toByte, 15.toByte, 27.toByte), basicMultiply ++ Array(23.toByte, 18.toByte, 28.toByte), - basicAdd ++ Array(16.toByte, 28.toByte, 29.toByte), - basicMultiply ++ Array(27.toByte, 29.toByte, 30.toByte), - basicMultiply ++ Array(13.toByte, 14.toByte, 31.toByte), - basicMultiply ++ Array(15.toByte, 15.toByte, 32.toByte), - basicMultiply ++ Array(31.toByte, 32.toByte, 33.toByte), - compareGreaterEqual ++ Array(30.toByte, 33.toByte, 34.toByte), - assertTrue ++ Array(34.toByte), + basicAdd ++ Array(16.toByte, 28.toByte, 29.toByte)) ++ + swapKValueCheck(27.toByte, 29.toByte, 15.toByte, 13.toByte, 14.toByte, 30.toByte) ++ Seq( // minus may put directly after load reserved token value A and B cdbvStateValMinus ++ Array(tokenAReservedStateVar.index, 0.toByte), cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 3.toByte, 25.toByte), @@ -325,16 +311,7 @@ object ContractVSwap { "numerator", "denominator", "amountOutBigInt", "amountType", "amountOut", "isValidAmountOut", "subValue", "updatedReserveA", "updatedReserveB", "updatedK", "KValue", "valueSquare","oldK", "isValidUpdatedK") - val swapExactTokenForBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ Seq( - basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(7.toByte), - compareGreater ++ Array(1.toByte, 7.toByte, 8.toByte), - assertTrue ++ Array(8.toByte), - cdbvrGetOrDefault ++ Array(tokenAReservedStateVar.index, 9.toByte), - cdbvrGetOrDefault ++ Array(tokenBReservedStateVar.index, 10.toByte), - basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(11.toByte), - basicConvert ++ Array(1.toByte, 11.toByte, 12.toByte), - basicConvert ++ Array(9.toByte, 11.toByte, 13.toByte), - basicConvert ++ Array(10.toByte, 11.toByte, 14.toByte), + val swapExactTokenForBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ commonSwapLoaded(1.toByte) ++ Seq( basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), basicMultiply ++ Array(12.toByte, 15.toByte, 16.toByte), basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(17.toByte), @@ -348,13 +325,8 @@ object ContractVSwap { assertTrue ++ Array(24.toByte), basicMinus ++ Array(13.toByte, 21.toByte, 25.toByte), basicMultiply ++ Array(25.toByte, 17.toByte, 26.toByte), - basicAdd ++ Array(18.toByte, 16.toByte, 27.toByte), - basicMultiply ++ Array(26.toByte, 27.toByte, 28.toByte), - basicMultiply ++ Array(13.toByte, 14.toByte, 29.toByte), - basicMultiply ++ Array(17.toByte, 17.toByte, 30.toByte), - basicMultiply ++ Array(29.toByte, 30.toByte, 31.toByte), - compareGreaterEqual ++ Array(28.toByte, 31.toByte, 32.toByte), - assertTrue ++ Array(32.toByte), + basicAdd ++ Array(18.toByte, 16.toByte, 27.toByte)) ++ + swapKValueCheck(26.toByte, 27.toByte, 15.toByte, 13.toByte, 14.toByte, 28.toByte) ++ Seq( cdbvStateValMinus ++ Array(tokenAReservedStateVar.index, 23.toByte), cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 3.toByte, 1.toByte), cdbvStateValAdd ++ Array(tokenBReservedStateVar.index, 1.toByte), From 9e5efa23df414dd6715e8c44a28b1fd82903267e Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 28 Oct 2020 10:27:28 +0800 Subject: [PATCH 102/391] add swap token for exact target token func --- .../blockchain/contract/ContractVSwap.scala | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index f99fee927..b797f1592 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -336,6 +336,43 @@ object ContractVSwap { swapDataType, swapExactTokenForBaseTokenFunctionOpcs) val swapExactTokenForBaseTokenTextualBytes: Array[Byte] = textualFunc("swapExactTokenForBaseToken", Seq(), swapExactTokenForBaseTokenPara) + val swapTokenForExactTargetTokenId: Short = 5 + val swapTokenForExactTargetTokenPara: Seq[String] = Seq("amountOut", "amountInMax", "deadline") ++ + commonSwapPara ++ + Seq("amountZero", "isValidAmountOut", "reserveA", "reserveB", + "bigIntType", "amountOutBigInt", "reserveABigInt", "reserveBBigInt", + "value1000", "mulValue", "numerator", "value997", "subValue", "denominator", + "valueOne", "amountInBigIntPre", "amountInBigInt", "amountType", + "amountIn", "isValidAmountIn", "updatedReserveB", "amountInWithOutFee", + "updatedReserveA", "updatedK", "KValue", "valueSquare", "oldK", "isValidUpdatedK") + val swapTokenForExactTargetTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ commonSwapLoaded(0.toByte) ++ Seq( + basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), + basicMultiply ++ Array(13.toByte, 15.toByte, 16.toByte), + basicMultiply ++ Array(16.toByte, 12.toByte, 17.toByte), + basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(18.toByte), + basicMinus ++ Array(14.toByte, 12.toByte, 19.toByte), + basicMultiply ++ Array(19.toByte, 18.toByte, 20.toByte), + basicConstantGet ++ DataEntry(BigInt(1).toByteArray, DataType.BigInteger).bytes ++ Array(21.toByte), + basicDivide ++ Array(17.toByte, 20.toByte, 22.toByte), + basicAdd ++ Array(22.toByte, 21.toByte, 23.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(24.toByte), + basicConvert ++ Array(23.toByte, 24.toByte, 25.toByte), + compareGreaterEqual ++ Array(1.toByte, 25.toByte, 26.toByte), + assertTrue ++ Array(26.toByte), + basicMultiply ++ Array(19.toByte, 15.toByte, 27.toByte), + basicMultiply ++ Array(23.toByte, 18.toByte, 28.toByte), + basicAdd ++ Array(16.toByte, 28.toByte, 29.toByte)) ++ + swapKValueCheck(29.toByte, 27.toByte, 15.toByte, 13.toByte, 14.toByte, 30.toByte) ++ Seq( + // minus may put directly after load reserved token value A and B + cdbvStateValMinus ++ Array(tokenBReservedStateVar.index, 0.toByte), + cdbvMapValMinus ++ Array(tokenABalanceMap.index, 3.toByte, 25.toByte), + cdbvStateValAdd ++ Array(tokenAReservedStateVar.index, 25.toByte), + cdbvMapValAdd ++ Array(tokenBBalanceMap.index, 3.toByte, 0.toByte) + ) + lazy val swapTokenForExactTargetTokenFunc: Array[Byte] = getFunctionBytes(swapTokenForExactTargetTokenId, publicFuncType, nonReturnType, + swapDataType, swapTokenForExactTargetTokenFunctionOpcs) + val swapTokenForExactTargetTokenTextualBytes: Array[Byte] = textualFunc("swapTokenForExactTargetToken", Seq(), swapTokenForExactTargetTokenPara) + // Textual } \ No newline at end of file From f6aebc17e66ecbb703341dbeb8dac5a8d9ebf013 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 29 Oct 2020 08:33:07 +0800 Subject: [PATCH 103/391] add swap exact token for target token func --- .../blockchain/contract/ContractVSwap.scala | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index b797f1592..0830ceed1 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -373,6 +373,40 @@ object ContractVSwap { swapDataType, swapTokenForExactTargetTokenFunctionOpcs) val swapTokenForExactTargetTokenTextualBytes: Array[Byte] = textualFunc("swapTokenForExactTargetToken", Seq(), swapTokenForExactTargetTokenPara) + val swapExactTokenForTargetTokenId: Short = 6 + val swapExactTokenForTargetTokenPara: Seq[String] = Seq("amountOutMin", "amountIn", "deadline") ++ + commonSwapPara ++ + Seq("amountZero", "isValidAmountIn", "reserveA", "reserveB", + "bigIntType", "amountInBigInt", "reserveABigInt", "reserveBBigInt", + "value997", "amountInWithOutFee", "value1000", "mulValue", + "numerator", "denominator", "amountOutBigInt", "amountType", "amountOut", + "isValidAmountOut", "subValue", "updatedReserveB", "updatedReserveA", + "updatedK", "KValue", "valueSquare","oldK", "isValidUpdatedK") + val swapExactTokenForTargetTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ commonSwapLoaded(1.toByte) ++ Seq( + basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), + basicMultiply ++ Array(12.toByte, 15.toByte, 16.toByte), + basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(17.toByte), + basicMultiply ++ Array(13.toByte, 17.toByte, 18.toByte), + basicMultiply ++ Array(14.toByte, 16.toByte, 19.toByte), + basicAdd ++ Array(18.toByte, 16.toByte, 20.toByte), + basicDivide ++ Array(19.toByte, 20.toByte, 21.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(22.toByte), + basicConvert ++ Array(21.toByte, 22.toByte, 23.toByte), + compareGreaterEqual ++ Array(23.toByte, 0.toByte, 24.toByte), + assertTrue ++ Array(24.toByte), + basicMinus ++ Array(14.toByte, 21.toByte, 25.toByte), + basicMultiply ++ Array(25.toByte, 17.toByte, 26.toByte), + basicAdd ++ Array(18.toByte, 16.toByte, 27.toByte)) ++ + swapKValueCheck(27.toByte, 26.toByte, 15.toByte, 13.toByte, 14.toByte, 28.toByte) ++ Seq( + cdbvStateValMinus ++ Array(tokenBReservedStateVar.index, 23.toByte), + cdbvMapValMinus ++ Array(tokenABalanceMap.index, 3.toByte, 1.toByte), + cdbvStateValAdd ++ Array(tokenAReservedStateVar.index, 1.toByte), + cdbvMapValAdd ++ Array(tokenBBalanceMap.index, 3.toByte, 23.toByte) + ) + lazy val swapExactTokenForTargetTokenFunc: Array[Byte] = getFunctionBytes(swapExactTokenForTargetTokenId, publicFuncType, nonReturnType, + swapDataType, swapExactTokenForTargetTokenFunctionOpcs) + val swapExactTokenForTargetTokenTextualBytes: Array[Byte] = textualFunc("swapExactTokenForTargetToken", Seq(), swapExactTokenForTargetTokenPara) + // Textual } \ No newline at end of file From 2564a48ba2543298331541b892032f305781e832 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 29 Oct 2020 09:01:22 +0800 Subject: [PATCH 104/391] add deposit trigger --- .../blockchain/contract/ContractGen.scala | 9 ++++ .../blockchain/contract/ContractVSwap.scala | 44 ++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractGen.scala b/src/main/scala/vsys/blockchain/contract/ContractGen.scala index a667ed10b..4aee6576e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractGen.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractGen.scala @@ -49,6 +49,12 @@ object ContractGen { val compareGreaterEqual = Array(10.toByte, 1.toByte) val compareGreater = Array(10.toByte, 2.toByte) + val compareLessEqual = Array(10.toByte, 3.toByte) + val compareLess = Array(10.toByte, 4.toByte) + val compareNumEqual = Array(10.toByte, 5.toByte) + val compareNumNotEqual = Array(10.toByte, 6.toByte) + val compareBytesEqual = Array(10.toByte, 7.toByte) + val compareBytesNotEqual = Array(10.toByte, 8.toByte) val basicAdd = Array(11.toByte, 1.toByte) val basicMinus = Array(11.toByte, 2.toByte) @@ -61,6 +67,9 @@ object ContractGen { val basicSqrtBigint = Array(11.toByte, 9.toByte) val basicConvert = Array(11.toByte, 10.toByte) + val conditionIf = Array(12.toByte, 1.toByte) + val conditionIfElse = Array(12.toByte, 1.toByte) + sealed case class StateVar(index: Byte, dataType: Byte) { lazy val arr: Array[Byte] = Array(index, dataType) } diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 0830ceed1..6a6055d85 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -19,7 +19,7 @@ object ContractVSwap { "tokenAReserved", "tokenBReserved", "totalSupply", "liquidityTokenLeft") val makerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) val tokenAIdStateVar: StateVar = StateVar(1.toByte, DataType.TokenId.id.toByte) - val tokeBIdStateVar: StateVar = StateVar(2.toByte, DataType.TokenId.id.toByte) + val tokenBIdStateVar: StateVar = StateVar(2.toByte, DataType.TokenId.id.toByte) val tokenLiquidityIdStateVar: StateVar = StateVar(3.toByte, DataType.TokenId.id.toByte) val swapStatusStateVar: StateVar = StateVar(4.toByte, DataType.Boolean.id.toByte) val minimumLiquidityStateVar: StateVar = StateVar(5.toByte, DataType.Amount.id.toByte) @@ -27,7 +27,7 @@ object ContractVSwap { val tokenBReservedStateVar: StateVar = StateVar(7.toByte, DataType.Amount.id.toByte) val totalSupplyStateVar: StateVar = StateVar(8.toByte, DataType.Amount.id.toByte) val liquidityTokenLeftStateVar: StateVar = StateVar(9.toByte, DataType.Amount.id.toByte) - lazy val stateVarSeq = Seq(makerStateVar.arr, tokenAIdStateVar.arr, tokeBIdStateVar.arr, tokenLiquidityIdStateVar.arr, + lazy val stateVarSeq = Seq(makerStateVar.arr, tokenAIdStateVar.arr, tokenBIdStateVar.arr, tokenLiquidityIdStateVar.arr, swapStatusStateVar.arr, minimumLiquidityStateVar.arr, tokenAReservedStateVar.arr, tokenBReservedStateVar.arr, totalSupplyStateVar.arr, liquidityTokenLeftStateVar.arr) lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) @@ -45,6 +45,46 @@ object ContractVSwap { // Initialization Trigger // Deposit Trigger + val depositId: Short = 1 + val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId") ++ + Seq("tokenAId", "tokenBId", "tokenLiquidityId", "isValidTokenId", + "isTokenA", "tokenAIfBlock", "isTokenB", "tokenBIfBlock", + "isTokenLiquidity", "tokenLiquidityIfBlock") + val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val depositTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(tokenAIdStateVar.index, 3.toByte), + cdbvrGet ++ Array(tokenBIdStateVar.index, 4.toByte), + cdbvrGet ++ Array(tokenLiquidityIdStateVar.index, 5.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + compareBytesEqual ++ Array(2.toByte, 3.toByte, 7.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(tokenABalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(8.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 9.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(tokenBBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(10.toByte), + compareBytesEqual ++ Array(2.toByte, 5.toByte, 11.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(liquidityBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(12.toByte), + conditionIf ++ Array(7.toByte, 8.toByte), + conditionIf ++ Array(9.toByte, 10.toByte), + conditionIf ++ Array(11.toByte, 12.toByte), + assertTrue ++ Array(6.toByte) + ) + lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) + val depositTextualBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) // WithDraw Trigger From 61cd7a31b204d8c2f7b48d0f1f61292136c56edd Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 29 Oct 2020 09:04:39 +0800 Subject: [PATCH 105/391] add withdraw trigger --- .../blockchain/contract/ContractVSwap.scala | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 6a6055d85..cbfd84fdf 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -87,6 +87,46 @@ object ContractVSwap { val depositTextualBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) // WithDraw Trigger + val withdrawId: Short = 2 + val withdrawPara: Seq[String] = Seq("withdrawer", "amount", "tokenId") ++ + Seq("tokenAId", "tokenBId", "tokenLiquidityId", "isValidTokenId", + "isTokenA", "tokenAIfBlock", "isTokenB", "tokenBIfBlock", + "isTokenLiquidity", "tokenLiquidityIfBlock") + val withdrawDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val withdrawTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(tokenAIdStateVar.index, 3.toByte), + cdbvrGet ++ Array(tokenBIdStateVar.index, 4.toByte), + cdbvrGet ++ Array(tokenLiquidityIdStateVar.index, 5.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + compareBytesEqual ++ Array(2.toByte, 3.toByte, 7.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(tokenABalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(8.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 9.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(10.toByte), + compareBytesEqual ++ Array(2.toByte, 5.toByte, 11.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(liquidityBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(12.toByte), + conditionIf ++ Array(7.toByte, 8.toByte), + conditionIf ++ Array(9.toByte, 10.toByte), + conditionIf ++ Array(11.toByte, 12.toByte), + assertTrue ++ Array(6.toByte) + ) + lazy val withdrawTrigger: Array[Byte] = getFunctionBytes(withdrawId, onWithDrawTriggerType, nonReturnType, withdrawDataType, withdrawTriggerOpcs) + val withdrawTextualBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) // Functions // Supersede From 72eb657edb11c4605da93fc9baa1cb4a9e3b7835 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 29 Oct 2020 09:12:07 +0800 Subject: [PATCH 106/391] add init trigger --- .../vsys/blockchain/contract/ContractVSwap.scala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index cbfd84fdf..e17d9699c 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -43,6 +43,22 @@ object ContractVSwap { lazy val stateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapTokenABalance, stateMapTokenBBalance, stateMapLiquidityBalance)) // Initialization Trigger + val initId: Short = 0 + val initPara: Seq[String] = Seq("tokenAId", "tokenBId", "liquidityTokenId", "minimumLiquidity") ++ + Seq("signer", "swapStatus") + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.Amount.id.toByte) + val initTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(4.toByte), + cdbvSet ++ Array(makerStateVar.index, 4.toByte), + cdbvSet ++ Array(tokenAIdStateVar.index, 0.toByte), + cdbvSet ++ Array(tokenBIdStateVar.index, 1.toByte), + cdbvSet ++ Array(tokenLiquidityIdStateVar.index, 2.toByte), + cdbvSet ++ Array(minimumLiquidityStateVar.index, 3.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + cdbvSet ++ Array(swapStatusStateVar.index, 5.toByte) + ) + lazy val initTrigger: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initTriggerOpcs) + val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) // Deposit Trigger val depositId: Short = 1 From 5a6cc94c48403ff65cdeb46a535ab1224044d02e Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 29 Oct 2020 09:17:49 +0800 Subject: [PATCH 107/391] add textual --- src/main/scala/vsys/blockchain/contract/ContractVSwap.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index e17d9699c..814a1a64e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -155,7 +155,7 @@ object ContractVSwap { assertSigner ++ Array(1.toByte), cdbvSet ++ Array(makerStateVar.index, 0.toByte)) lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) - val supersedeFuncBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) + val supersedeTextualBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) // Set Swap val setSwapId: Short = 1 @@ -504,5 +504,8 @@ object ContractVSwap { val swapExactTokenForTargetTokenTextualBytes: Array[Byte] = textualFunc("swapExactTokenForTargetToken", Seq(), swapExactTokenForTargetTokenPara) // Textual + lazy val triggerTextual: Array[Byte] = Deser.serializeArrays(Seq(initTextualBytes, depositTextualBytes, withdrawTextualBytes)) + lazy val descriptorTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeTextualBytes, setSwapTextualBytes, addLiquidityTextualBytes, removeLiquidityTextualBytes, + swapTokenForExactBaseTokenTextualBytes, swapExactTokenForBaseTokenTextualBytes, swapTokenForExactTargetTokenTextualBytes, swapExactTokenForTargetTokenTextualBytes)) } \ No newline at end of file From 35d56512e3a0a2e7810db72a2d471ab838c1b0d7 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 29 Oct 2020 09:25:46 +0800 Subject: [PATCH 108/391] package to the contract --- .../scala/vsys/blockchain/contract/ContractVSwap.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 814a1a64e..86d465b24 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -7,11 +7,12 @@ import vsys.utils.serialization.Deser object ContractVSwap { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), - Seq(), // Triggers - Seq(), // Functions + Seq(initTrigger, depositTrigger, withdrawTrigger), // Triggers + Seq(supersedeFunc, setSwapFunc, addLiquidityFunc, removeLiquidityFunc, swapTokenForExactBaseTokenFunc, + swapExactTokenForBaseTokenFunc, swapTokenForExactTargetTokenFunc, swapExactTokenForTargetTokenFunc), // Functions stateVarSeq, // StateVars stateMapSeq, // StateMaps - Seq() // Textual + Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual) // Textual ).explicitGet() // State Var From e8b3f90d748978f4b76ae6e4ba8e593d7485f0de Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 29 Oct 2020 11:38:38 +0800 Subject: [PATCH 109/391] add v option state var --- .../blockchain/contract/ContractVOption.scala | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/scala/vsys/blockchain/contract/ContractVOption.scala diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala new file mode 100644 index 000000000..2c7456b70 --- /dev/null +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -0,0 +1,54 @@ +package vsys.blockchain.contract + +import com.google.common.primitives.{Ints, Longs} +import vsys.blockchain.contract.ContractGen._ +import vsys.blockchain.state._ +import vsys.utils.serialization.Deser + +object ContractVOption { + lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(), // Triggers + Seq(), // Functions + stateVarSeq, // StateVars + Seq(), // StateMaps + Seq() // Textual + ).explicitGet() + + // State Var + val stateVarName = List("maker", "baseTokenId", "targetTokenId", "optionTokenId", "proofTokenId", "executeTime", + "executeDeadline", "optionStatus", "maxIssueNum", "reservedOption", "reservedProof", + "price", "priceUnit", "tokenLocked", "tokenCollected") + val makerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) + val baseTokenIdStateVar: StateVar = StateVar(1.toByte, DataType.TokenId.id.toByte) + val targetTokenIdStateVar: StateVar = StateVar(2.toByte, DataType.TokenId.id.toByte) + val optionTokenIdStateVar: StateVar = StateVar(3.toByte, DataType.TokenId.id.toByte) + val proofTokenIdStateVar: StateVar = StateVar(4.toByte, DataType.TokenId.id.toByte) + val executeTimeStateVar: StateVar = StateVar(5.toByte, DataType.Timestamp.id.toByte) + val executeDeadlineStateVar: StateVar = StateVar(6.toByte, DataType.Timestamp.id.toByte) + val optionStatusStateVar: StateVar = StateVar(7.toByte, DataType.Boolean.id.toByte) + val maxIssueNumStateVar: StateVar = StateVar(8.toByte, DataType.Amount.id.toByte) + val reservedOptionStateVar: StateVar = StateVar(9.toByte, DataType.Amount.id.toByte) + val reservedProofStateVar: StateVar = StateVar(10.toByte, DataType.Amount.id.toByte) + val priceStateVar: StateVar = StateVar(11.toByte, DataType.Amount.id.toByte) + val priceUnitStateVar: StateVar = StateVar(12.toByte, DataType.Amount.id.toByte) + val tokenLockedStateVar: StateVar = StateVar(13.toByte, DataType.Amount.id.toByte) + val tokenCollectedStateVar: StateVar = StateVar(14.toByte, DataType.Amount.id.toByte) + lazy val stateVarSeq = Seq(makerStateVar.arr, baseTokenIdStateVar.arr, targetTokenIdStateVar.arr, + optionTokenIdStateVar.arr, proofTokenIdStateVar.arr, + executeTimeStateVar.arr, executeDeadlineStateVar.arr, optionStatusStateVar.arr, + maxIssueNumStateVar.arr, reservedOptionStateVar.arr, reservedProofStateVar.arr, + priceStateVar.arr, priceUnitStateVar.arr, tokenLockedStateVar.arr, tokenCollectedStateVar.arr) + lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) + + // State Map + + // Initialization Trigger + + // Deposit Trigger + + // WithDraw Trigger + + // Functions + + // Textual +} \ No newline at end of file From 388d621ceb47af4ccf234b77e0aacfc69dd5b1c2 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 29 Oct 2020 11:44:54 +0800 Subject: [PATCH 110/391] add v option state map --- .../vsys/blockchain/contract/ContractVOption.scala | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index 2c7456b70..3976f0160 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -10,7 +10,7 @@ object ContractVOption { Seq(), // Triggers Seq(), // Functions stateVarSeq, // StateVars - Seq(), // StateMaps + stateMapSeq, // StateMaps Seq() // Textual ).explicitGet() @@ -41,6 +41,18 @@ object ContractVOption { lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map + val stateMapBaseTokenBalance = List("baseTokenBalance", "userAddress", "balance") + val stateMapTargetTokenBalance = List("targetTokenBalance", "userAddress", "balance") + val stateMapOptionTokenBalance = List("optionTokenBalance", "userAddress", "balance") + val stateMapProofTokenBalance = List("proofTokenBalance", "userAddress", "balance") + val baseTokenBalanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val targetTokenBalanceMap: StateMap = StateMap(1.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val optionTokenBalanceMap: StateMap = StateMap(2.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val proofTokenBalanceMap: StateMap = StateMap(3.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + + lazy val stateMapSeq = Seq(baseTokenBalanceMap.arr, targetTokenBalanceMap.arr, optionTokenBalanceMap.arr, proofTokenBalanceMap.arr) + lazy val stateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapBaseTokenBalance, stateMapTargetTokenBalance, + stateMapOptionTokenBalance, stateMapProofTokenBalance)) // Initialization Trigger From 0e189c8039e87a42ffc949f832db1cb961cdd6ce Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 30 Oct 2020 10:25:01 +0800 Subject: [PATCH 111/391] add init trigger --- .../blockchain/contract/ContractVOption.scala | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index 3976f0160..cdb7c7a47 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -55,6 +55,25 @@ object ContractVOption { stateMapOptionTokenBalance, stateMapProofTokenBalance)) // Initialization Trigger + val initId: Short = 0 + val initPara: Seq[String] = Seq("baseTokenId", "targetTokenId", "optionTokenId", "proofTokenId", "executeTime", "executeDeadline") ++ + Seq("signer", "optionStatus") + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.TokenId.id.toByte,DataType.TokenId.id.toByte, + DataType.TokenId.id.toByte, DataType.Timestamp.id.toByte, DataType.Timestamp.id.toByte) + val initTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(6.toByte), + cdbvSet ++ Array(makerStateVar.index, 6.toByte), + cdbvSet ++ Array(baseTokenIdStateVar.index, 0.toByte), + cdbvSet ++ Array(targetTokenIdStateVar.index, 1.toByte), + cdbvSet ++ Array(optionTokenIdStateVar.index, 2.toByte), + cdbvSet ++ Array(proofTokenIdStateVar.index, 3.toByte), + cdbvSet ++ Array(executeTimeStateVar.index, 4.toByte), + cdbvSet ++ Array(executeDeadlineStateVar.index, 5.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + cdbvSet ++ Array(optionStatusStateVar.index, 5.toByte) + ) + lazy val initTrigger: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initTriggerOpcs) + val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) // Deposit Trigger From 348cc6791d771f10971e007b17a0fc036d3d28a0 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 30 Oct 2020 10:33:19 +0800 Subject: [PATCH 112/391] add deposit trigger --- .../blockchain/contract/ContractVOption.scala | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index cdb7c7a47..69564ff5b 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -76,6 +76,55 @@ object ContractVOption { val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) // Deposit Trigger + val depositId: Short = 1 + val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId") ++ + Seq("baseTokenId", "targetTokenId", "optionTokenId", "proofTokenId", "isValidTokenId", + "isBaseToken", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock", + "isOptionToken", "optionTokenIfBlock", "isProofToken", "proofTokenIfBlock") + val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val depositTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(baseTokenIdStateVar.index, 3.toByte), + cdbvrGet ++ Array(targetTokenIdStateVar.index, 4.toByte), + cdbvrGet ++ Array(optionTokenIdStateVar.index, 5.toByte), + cdbvrGet ++ Array(proofTokenIdStateVar.index, 6.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + compareBytesEqual ++ Array(2.toByte, 3.toByte, 8.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(9.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 10.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(11.toByte), + compareBytesEqual ++ Array(2.toByte, 5.toByte, 12.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(optionTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(13.toByte), + compareBytesEqual ++ Array(2.toByte, 6.toByte, 14.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(optionTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(15.toByte), + conditionIf ++ Array(8.toByte, 9.toByte), + conditionIf ++ Array(10.toByte, 11.toByte), + conditionIf ++ Array(12.toByte, 13.toByte), + conditionIf ++ Array(14.toByte, 15.toByte), + assertTrue ++ Array(7.toByte) + ) + lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) + val depositTextualBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) // WithDraw Trigger From 4a786c58b79a82fe08ff02e5ec6d72396728fe3c Mon Sep 17 00:00:00 2001 From: zl730 Date: Sat, 31 Oct 2020 10:14:07 +0800 Subject: [PATCH 113/391] fix prefix bug --- src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala index 774d7636a..8f2ec21f2 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala @@ -14,7 +14,7 @@ object IfOpcDiff extends OpcDiffer { def executeOpcBlock(context: ExecutionContext, opcBlock: DataEntry, dataStack: Seq[DataEntry]): Either[ValidationError, (OpcDiff, Seq[DataEntry])] = { opcBlock.dataType match { case DataType.OpcBlock => { - Try(Deser.parseArrays(opcBlock.data)) match { + Try(Deser.parseArrays(DataEntry.OpcBlock.deserializer(opcBlock.data))) match { case Success(opclines) => { opclines.foldLeft(Right((OpcDiff.empty, dataStack)): Either[ValidationError, (OpcDiff, Seq[DataEntry])]) { case (acc, opc) => acc.flatMap { case (oldDiff, oldData) => { From ce4cb5051beb14616b617ce5e93b7c6c976289e0 Mon Sep 17 00:00:00 2001 From: zl730 Date: Sat, 31 Oct 2020 10:17:31 +0800 Subject: [PATCH 114/391] fix class --- src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala index 8f2ec21f2..6d236cb73 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala @@ -14,7 +14,7 @@ object IfOpcDiff extends OpcDiffer { def executeOpcBlock(context: ExecutionContext, opcBlock: DataEntry, dataStack: Seq[DataEntry]): Either[ValidationError, (OpcDiff, Seq[DataEntry])] = { opcBlock.dataType match { case DataType.OpcBlock => { - Try(Deser.parseArrays(DataEntry.OpcBlock.deserializer(opcBlock.data))) match { + Try(Deser.parseArrays(DataType.OpcBlock.deserializer(opcBlock.data))) match { case Success(opclines) => { opclines.foldLeft(Right((OpcDiff.empty, dataStack)): Either[ValidationError, (OpcDiff, Seq[DataEntry])]) { case (acc, opc) => acc.flatMap { case (oldDiff, oldData) => { From b4140be79748afac2adf6ca79918138f5c6b5ba7 Mon Sep 17 00:00:00 2001 From: zl730 Date: Sat, 31 Oct 2020 11:55:50 +0800 Subject: [PATCH 115/391] Update IfOpcDiffTest.scala --- .../scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala index 20e1dea41..8639bd642 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala @@ -33,7 +33,7 @@ class IfOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPro Seq.empty) should be (Left(ContractDataTypeMismatch)) IfOpcDiff.executeOpcBlock(executionContext, DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), - Seq.empty) should be (Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()),List()))) + Seq.empty) should be (Left(ContractInvalidOPCData)) IfOpcDiff.executeOpcBlock(executionContext, DataEntry(Shorts.toByteArray(1), DataType.OpcBlock), Seq.empty) should be (Left(ContractInvalidOPCData)) @@ -78,4 +78,4 @@ class IfOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPro DataEntry(Shorts.toByteArray(1), DataType.OpcBlock))) should be ( Left(ContractInvalidOPCData)) } -} \ No newline at end of file +} From 2b621c913eeab3808dbae343227e6f15195b6e8f Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 2 Nov 2020 09:43:10 +0800 Subject: [PATCH 116/391] add withdraw trigger --- .../blockchain/contract/ContractVOption.scala | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index 69564ff5b..25886d15b 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -7,7 +7,7 @@ import vsys.utils.serialization.Deser object ContractVOption { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), - Seq(), // Triggers + Seq(initTrigger, depositTrigger, withdrawTrigger), // Triggers Seq(), // Functions stateVarSeq, // StateVars stateMapSeq, // StateMaps @@ -127,6 +127,55 @@ object ContractVOption { val depositTextualBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) // WithDraw Trigger + val withdrawId: Short = 2 + val withdrawPara: Seq[String] = Seq("withdrawer", "amount", "tokenId") ++ + Seq("baseTokenId", "targetTokenId", "optionTokenId", "proofTokenId", "isValidTokenId", + "isBaseToken", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock", + "isOptionToken", "optionTokenIfBlock", "isProofToken", "proofTokenIfBlock") + val withdrawDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val withdrawTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(baseTokenIdStateVar.index, 3.toByte), + cdbvrGet ++ Array(targetTokenIdStateVar.index, 4.toByte), + cdbvrGet ++ Array(optionTokenIdStateVar.index, 5.toByte), + cdbvrGet ++ Array(proofTokenIdStateVar.index, 6.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + compareBytesEqual ++ Array(2.toByte, 3.toByte, 8.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(9.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 10.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(11.toByte), + compareBytesEqual ++ Array(2.toByte, 5.toByte, 12.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(optionTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(13.toByte), + compareBytesEqual ++ Array(2.toByte, 6.toByte, 14.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(optionTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(15.toByte), + conditionIf ++ Array(8.toByte, 9.toByte), + conditionIf ++ Array(10.toByte, 11.toByte), + conditionIf ++ Array(12.toByte, 13.toByte), + conditionIf ++ Array(14.toByte, 15.toByte), + assertTrue ++ Array(7.toByte) + ) + lazy val withdrawTrigger: Array[Byte] = getFunctionBytes(withdrawId, onWithDrawTriggerType, nonReturnType, withdrawDataType, withdrawTriggerOpcs) + val withdrawTextualBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) // Functions From 21eead9fbaf3c4549021df6e9a73b8bbe8d57330 Mon Sep 17 00:00:00 2001 From: zl730 Date: Mon, 2 Nov 2020 09:43:44 +0800 Subject: [PATCH 117/391] fix test --- .../scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala | 4 +++- .../vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala index 6d236cb73..61108d439 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/IfOpcDiff.scala @@ -14,7 +14,9 @@ object IfOpcDiff extends OpcDiffer { def executeOpcBlock(context: ExecutionContext, opcBlock: DataEntry, dataStack: Seq[DataEntry]): Either[ValidationError, (OpcDiff, Seq[DataEntry])] = { opcBlock.dataType match { case DataType.OpcBlock => { - Try(Deser.parseArrays(DataType.OpcBlock.deserializer(opcBlock.data))) match { + val opcBytes = DataType.OpcBlock.deserializer(opcBlock.data) + if(opcBytes.length == 0) Right((OpcDiff.empty, dataStack)) + else Try(Deser.parseArrays(opcBytes)) match { case Success(opclines) => { opclines.foldLeft(Right((OpcDiff.empty, dataStack)): Either[ValidationError, (OpcDiff, Seq[DataEntry])]) { case (acc, opc) => acc.flatMap { case (oldDiff, oldData) => { diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala index 8639bd642..fb91cdb12 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/IfOpcDiffTest.scala @@ -33,9 +33,9 @@ class IfOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPro Seq.empty) should be (Left(ContractDataTypeMismatch)) IfOpcDiff.executeOpcBlock(executionContext, DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), - Seq.empty) should be (Left(ContractInvalidOPCData)) + Seq.empty) should be (Right((OpcDiff(Map(),Map(),Map(),Map(),Map(),Map(),Map(),Map()),List()))) IfOpcDiff.executeOpcBlock(executionContext, - DataEntry(Shorts.toByteArray(1), DataType.OpcBlock), + DataEntry(Array[Byte](0, 2, 0, 1), DataType.OpcBlock), Seq.empty) should be (Left(ContractInvalidOPCData)) IfOpcDiff.runCondition( @@ -75,7 +75,7 @@ class IfOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPro Array[Byte](2.toByte, 0.toByte, 1.toByte, 2.toByte), Seq[DataEntry](DataEntry(Array(0.toByte), DataType.Boolean), DataEntry(Shorts.toByteArray(0), DataType.OpcBlock), - DataEntry(Shorts.toByteArray(1), DataType.OpcBlock))) should be ( + DataEntry(Array[Byte](0, 2, 0, 1), DataType.OpcBlock))) should be ( Left(ContractInvalidOPCData)) } } From 7f724c679d4465517af68cceacfbf51fd5802abf Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 2 Nov 2020 11:11:01 +0800 Subject: [PATCH 118/391] add supersede func --- .../vsys/blockchain/contract/ContractVOption.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index 25886d15b..d9dab0bc0 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -178,6 +178,17 @@ object ContractVOption { val withdrawTextualBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) // Functions + // Supersede + val supersedeId: Short = 0 + val supersedePara: Seq[String] = Seq("newOwner", + "maker") + val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val supersedeOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(makerStateVar.index, 1.toByte), + assertSigner ++ Array(1.toByte), + cdbvSet ++ Array(makerStateVar.index, 0.toByte)) + lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) + val supersedeTextualBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) // Textual } \ No newline at end of file From c7c89bbfdcc1f11f7dbd75a0ca8b1066f4364b76 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 3 Nov 2020 09:06:25 +0800 Subject: [PATCH 119/391] add activate option fuc --- .../blockchain/contract/ContractVOption.scala | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index d9dab0bc0..b978828a3 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -190,5 +190,41 @@ object ContractVOption { lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) val supersedeTextualBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) + // Activate Option + val activateId: Short = 1 + val activatePara: Seq[String] = Seq("maxIssueNum", "price", "priceUnit") ++ + Seq("maker", "optionStatus", "valueFalse", "amountZero", "isValidIssueNum", + "isValidPrice", "isValidPriceUnit", "optionTokenNum", "proofTokenNum", "valueTrue") + val activateDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) + val activateOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(makerStateVar.index, 3.toByte), + assertCaller ++ Array(3.toByte), + cdbvrGet ++ Array(optionStatusStateVar.index, 4.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + assertEqual ++ Array(4.toByte, 5.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(6.toByte), + compareGreater ++ Array(0.toByte, 6.toByte, 7.toByte), + assertTrue ++ Array(7.toByte), + compareGreater ++ Array(1.toByte, 6.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + compareGreater ++ Array(2.toByte, 6.toByte, 9.toByte), + assertTrue ++ Array(9.toByte), + cdbvrMapGetOrDefault ++ Array(optionTokenBalanceMap.index, 3.toByte, 10.toByte), + cdbvrMapGetOrDefault ++ Array(proofTokenBalanceMap.index, 3.toByte, 11.toByte), + assertEqual ++ Array(10.toByte, 0.toByte), + assertEqual ++ Array(11.toByte, 0.toByte), + cdbvMapValMinus ++ Array(optionTokenBalanceMap.index, 3.toByte, 0.toByte), + cdbvMapValMinus ++ Array(proofTokenBalanceMap.index, 3.toByte, 0.toByte), + cdbvSet ++ Array(maxIssueNumStateVar.index, 0.toByte), + cdbvStateValAdd ++ Array(reservedOptionStateVar.index, 0.toByte), + cdbvStateValAdd ++ Array(reservedProofStateVar.index, 0.toByte), + cdbvSet ++ Array(priceStateVar.index, 1.toByte), + cdbvSet ++ Array(priceUnitStateVar.index, 2.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(12.toByte), + cdbvSet ++ Array(optionStatusStateVar.index, 12.toByte) + ) + lazy val activateFunc: Array[Byte] = getFunctionBytes(activateId, publicFuncType, nonReturnType, activateDataType, activateOpcs) + val activateTextualBytes: Array[Byte] = textualFunc("activate", Seq(), activatePara) + // Textual } \ No newline at end of file From dae88c21d7602834a4cd256f11ad856f257b94a5 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 3 Nov 2020 09:14:51 +0800 Subject: [PATCH 120/391] add common option code --- .../vsys/blockchain/contract/ContractVOption.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index b978828a3..e64e6c731 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -226,5 +226,16 @@ object ContractVOption { lazy val activateFunc: Array[Byte] = getFunctionBytes(activateId, publicFuncType, nonReturnType, activateDataType, activateOpcs) val activateTextualBytes: Array[Byte] = textualFunc("activate", Seq(), activatePara) + // Common Option Code + val commonOptionPara: Seq[String] = Seq("amount") ++ + Seq("caller", "OptionStatus", "currentTime") + val commonOptionDataType: Array[Byte] = Array(DataType.Amount.id.toByte) + val commonOptionOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(1.toByte), + cdbvrGet ++ Array(optionStatusStateVar.index, 2.toByte), + assertTrue ++ Array(2.toByte), + loadTimestamp ++ Array(3.toByte) + ) + // Textual } \ No newline at end of file From ffc5fd81e2be4594abdbb873cc9e4eb88dcb7796 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 3 Nov 2020 09:26:35 +0800 Subject: [PATCH 121/391] add mint option code --- .../blockchain/contract/ContractVOption.scala | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index e64e6c731..8e91ff417 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -237,5 +237,24 @@ object ContractVOption { loadTimestamp ++ Array(3.toByte) ) + // Mint Option + val mintId: Short = 2 + val mintPara: Seq[String] = commonOptionPara ++ + Seq("executeTime", "isValidTime") + val mintOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(executeTimeStateVar.index, 4.toByte), + compareGreater ++ Array(4.toByte, 3.toByte, 5.toByte), + assertTrue ++ Array(5.toByte), + cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 1.toByte, 0.toByte), + cdbvStateValMinus ++ Array(reservedOptionStateVar.index, 0.toByte), + cdbvStateValMinus ++ Array(reservedProofStateVar.index, 0.toByte), + cdbvStateValAdd ++ Array(tokenLockedStateVar.index, 0.toByte), + cdbvMapValAdd ++ Array(optionTokenBalanceMap.index, 1.toByte, 0.toByte), + cdbvMapValAdd ++ Array(proofTokenBalanceMap.index, 1.toByte, 0.toByte) + ) + lazy val mintFunc: Array[Byte] = getFunctionBytes( mintId, publicFuncType, nonReturnType, commonOptionDataType, mintOpcs) + val mintTextualBytes: Array[Byte] = textualFunc("Mint", Seq(), mintPara) + + // Textual } \ No newline at end of file From 300c2fa5b2c61d700d6f443fdd37f8d870c648d0 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 3 Nov 2020 10:08:08 +0800 Subject: [PATCH 122/391] add unlock target token func --- .../blockchain/contract/ContractVOption.scala | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index 8e91ff417..85fba34ba 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -241,7 +241,7 @@ object ContractVOption { val mintId: Short = 2 val mintPara: Seq[String] = commonOptionPara ++ Seq("executeTime", "isValidTime") - val mintOpcs: Seq[Array[Byte]] = Seq( + val mintOpcs: Seq[Array[Byte]] = commonOptionOpcs ++ Seq( cdbvrGet ++ Array(executeTimeStateVar.index, 4.toByte), compareGreater ++ Array(4.toByte, 3.toByte, 5.toByte), assertTrue ++ Array(5.toByte), @@ -253,8 +253,25 @@ object ContractVOption { cdbvMapValAdd ++ Array(proofTokenBalanceMap.index, 1.toByte, 0.toByte) ) lazy val mintFunc: Array[Byte] = getFunctionBytes( mintId, publicFuncType, nonReturnType, commonOptionDataType, mintOpcs) - val mintTextualBytes: Array[Byte] = textualFunc("Mint", Seq(), mintPara) + val mintTextualBytes: Array[Byte] = textualFunc("mint", Seq(), mintPara) + // Unlock Option + val unlockId: Short = 3 + val unlockPara: Seq[String] = commonOptionPara ++ + Seq("executeDeadline", "isValidTime") + val unlockOpcs: Seq[Array[Byte]] = commonOptionOpcs ++ Seq( + cdbvrGet ++ Array(executeDeadlineStateVar.index, 4.toByte), + compareGreater ++ Array(4.toByte, 3.toByte, 5.toByte), + assertTrue ++ Array(5.toByte), + cdbvMapValMinus ++ Array(optionTokenBalanceMap.index, 1.toByte, 0.toByte), + cdbvMapValMinus ++ Array(proofTokenBalanceMap.index, 1.toByte, 0.toByte), + cdbvStateValAdd ++ Array(reservedOptionStateVar.index, 0.toByte), + cdbvStateValAdd ++ Array(reservedProofStateVar.index, 0.toByte), + cdbvStateValMinus ++ Array(tokenLockedStateVar.index, 0.toByte), + cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 1.toByte, 0.toByte) + ) + lazy val unlockFunc: Array[Byte] = getFunctionBytes( unlockId, publicFuncType, nonReturnType, commonOptionDataType, unlockOpcs) + val unlockTextualBytes: Array[Byte] = textualFunc("unlock", Seq(), unlockPara) // Textual } \ No newline at end of file From 7a58f3d6f1f60103f970812ddc2d99dc20b8c8da Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 4 Nov 2020 10:45:13 +0800 Subject: [PATCH 123/391] add execute option func --- .../blockchain/contract/ContractVOption.scala | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index 85fba34ba..a5995cce1 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -273,5 +273,41 @@ object ContractVOption { lazy val unlockFunc: Array[Byte] = getFunctionBytes( unlockId, publicFuncType, nonReturnType, commonOptionDataType, unlockOpcs) val unlockTextualBytes: Array[Byte] = textualFunc("unlock", Seq(), unlockPara) + // Execute Option + val executeId: Short = 4 + val executePara: Seq[String] = commonOptionPara ++ + Seq("executeDeadline", "isBeforeDeadline", "executeTime", "isValidToExecute", + "price", "priceUnit", "bigIntType", "amountBigInt", "priceBigInt", "priceUnitBigInt", + "costWithUnitBigInt", "costBigInt", "amountType", "cost", "amountOne", "fixedCost") + val executeOpcs: Seq[Array[Byte]] = commonOptionOpcs ++ Seq( + cdbvrGet ++ Array(executeDeadlineStateVar.index, 4.toByte), + compareGreater ++ Array(4.toByte, 3.toByte, 5.toByte), + assertTrue ++ Array(5.toByte), + cdbvrGet ++ Array(executeTimeStateVar.index, 6.toByte), + compareGreaterEqual ++ Array(3.toByte, 6.toByte, 7.toByte), + assertTrue ++ Array(7.toByte), + cdbvMapValMinus ++ Array(optionTokenBalanceMap.index, 1.toByte, 0.toByte), + cdbvStateValAdd ++ Array(reservedOptionStateVar.index, 0.toByte), + cdbvrGet ++ Array(priceStateVar.index, 8.toByte), + cdbvrGet ++ Array(priceUnitStateVar.index, 9.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(10.toByte), + basicConvert ++ Array(0.toByte, 10.toByte, 11.toByte), + basicConvert ++ Array(8.toByte, 10.toByte, 12.toByte), + basicConvert ++ Array(9.toByte, 10.toByte, 13.toByte), + basicMultiply ++ Array(11.toByte, 12.toByte, 14.toByte), + basicDivide ++ Array(14.toByte, 13.toByte, 15.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(16.toByte), + basicConvert ++ Array(15.toByte, 16.toByte, 17.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1L), DataType.Amount).bytes ++ Array(18.toByte), + basicAdd ++ Array(17.toByte, 18.toByte, 19.toByte), + cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 1.toByte, 19.toByte), + cdbvStateValAdd ++ Array(tokenCollectedStateVar.index, 19.toByte), + cdbvStateValMinus ++ Array(tokenLockedStateVar.index, 0.toByte), + cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 1.toByte, 0.toByte) + ) + lazy val executeFunc: Array[Byte] = getFunctionBytes( executeId, publicFuncType, nonReturnType, commonOptionDataType, executeOpcs) + val executeTextualBytes: Array[Byte] = textualFunc("execute", Seq(), executePara) + + // Textual } \ No newline at end of file From 6915bb79bfded35323b274299d353bf87124ec83 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 5 Nov 2020 08:47:53 +0800 Subject: [PATCH 124/391] add collect func --- .../blockchain/contract/ContractVOption.scala | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index a5995cce1..29ae2ed25 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -308,6 +308,45 @@ object ContractVOption { lazy val executeFunc: Array[Byte] = getFunctionBytes( executeId, publicFuncType, nonReturnType, commonOptionDataType, executeOpcs) val executeTextualBytes: Array[Byte] = textualFunc("execute", Seq(), executePara) + val collectId: Short = 5 + val collectPara: Seq[String] = commonOptionPara ++ + Seq("executeDeadline", "isValidTime", "maxIssue", "reservedProof", "isValidCollect", "uncollectedProof", + "bigIntType", "baseNumber", "baseNumberBigInt", "amountBigInt", "uncollectedProofBigInt", + "baseNumerator", "baseCollectBigInt", "amountType", "baseCollect", "targetNumber", "targetNumberBigInt", + "targetNumerator", "targetCollectBigInt", "targetCollect") + val collectOpcs: Seq[Array[Byte]] = commonOptionOpcs ++ Seq( + cdbvrGet ++ Array(executeDeadlineStateVar.index, 4.toByte), + compareGreater ++ Array(3.toByte, 4.toByte, 5.toByte), + assertTrue ++ Array(5.toByte), + cdbvrGet ++ Array(maxIssueNumStateVar.index, 6.toByte), + cdbvrGetOrDefault ++ Array(reservedProofStateVar.index, 7.toByte), + compareGreater ++ Array(6.toByte, 7.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + basicMinus ++ Array(6.toByte, 7.toByte, 9.toByte), + cdbvMapValMinus ++ Array(proofTokenBalanceMap.index, 1.toByte, 0.toByte), + cdbvStateValAdd ++ Array(reservedProofStateVar.index, 0.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(10.toByte), + cdbvrGetOrDefault ++ Array(tokenCollectedStateVar.index, 11.toByte), + basicConvert ++ Array(11.toByte, 10.toByte, 12.toByte), + basicConvert ++ Array(0.toByte, 10.toByte, 13.toByte), + basicConvert ++ Array(9.toByte, 10.toByte, 14.toByte), + basicMultiply ++ Array(12.toByte, 13.toByte, 15.toByte), + basicDivide ++ Array(15.toByte, 14.toByte, 16.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(17.toByte), + basicConvert ++ Array(16.toByte, 17.toByte, 18.toByte), + cdbvrGetOrDefault ++ Array(tokenLockedStateVar.index, 19.toByte), + basicConvert ++ Array(19.toByte, 10.toByte, 20.toByte), + basicMultiply ++ Array(20.toByte, 13.toByte, 21.toByte), + basicDivide ++ Array(21.toByte, 14.toByte, 22.toByte), + basicConvert ++ Array(22.toByte, 17.toByte, 23.toByte), + cdbvStateValMinus ++ Array(tokenCollectedStateVar.index, 18.toByte), + cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 1.toByte, 18.toByte), + cdbvStateValMinus ++ Array(tokenLockedStateVar.index, 23.toByte), + cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 1.toByte, 23.toByte) + ) + lazy val collectFunc: Array[Byte] = getFunctionBytes( collectId, publicFuncType, nonReturnType, commonOptionDataType, collectOpcs) + val collectTextualBytes: Array[Byte] = textualFunc("collect", Seq(), collectPara) + // Textual } \ No newline at end of file From 1ca6f53fbcb5da5f30f09dd317924c4fceafe19e Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 5 Nov 2020 08:50:18 +0800 Subject: [PATCH 125/391] add textual --- .../scala/vsys/blockchain/contract/ContractVOption.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index 29ae2ed25..a81cad02b 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -347,6 +347,9 @@ object ContractVOption { lazy val collectFunc: Array[Byte] = getFunctionBytes( collectId, publicFuncType, nonReturnType, commonOptionDataType, collectOpcs) val collectTextualBytes: Array[Byte] = textualFunc("collect", Seq(), collectPara) - // Textual + lazy val triggerTextual: Array[Byte] = Deser.serializeArrays(Seq(initTextualBytes, depositTextualBytes, withdrawTextualBytes)) + lazy val descriptorTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeTextualBytes, activateTextualBytes, mintTextualBytes, + unlockTextualBytes, executeTextualBytes, collectTextualBytes)) + } \ No newline at end of file From 76ce35d496e142e066bfccee96ae211e32976639 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 5 Nov 2020 08:54:34 +0800 Subject: [PATCH 126/391] complete v option contract --- src/main/scala/vsys/blockchain/contract/ContractVOption.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index a81cad02b..c3ddac15b 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -8,10 +8,10 @@ import vsys.utils.serialization.Deser object ContractVOption { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), Seq(initTrigger, depositTrigger, withdrawTrigger), // Triggers - Seq(), // Functions + Seq(supersedeFunc, activateFunc, mintFunc, unlockFunc, executeFunc, collectFunc), // Functions stateVarSeq, // StateVars stateMapSeq, // StateMaps - Seq() // Textual + Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual) // Textual ).explicitGet() // State Var From 8b5c891269e0153d4d6cee539029f2e54b02070d Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 13 Nov 2020 09:42:50 +0800 Subject: [PATCH 127/391] add v stable swap state var --- .../contract/ContractVStableSwap.scala | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala new file mode 100644 index 000000000..e67415cb9 --- /dev/null +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -0,0 +1,47 @@ +package vsys.blockchain.contract + +import com.google.common.primitives.Ints +import vsys.blockchain.contract.ContractGen._ +import vsys.blockchain.state._ +import vsys.utils.serialization.Deser + +object ContractVStableSwap { + lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(), // Triggers + Seq(), // Functions + stateVarSeq, // StateVars + Seq(), // StateMaps + Seq() // Textual + ).explicitGet() + + // State Var + val stateVarName = List("maker", "baseTokenId", "targetTokenId", "minSwapAmount", "maxSwapAmount", + "lastUpdateTime", "updateGap", "feeBase", "feeTarget") + val makerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) + val baseTokenIdStateVar: StateVar = StateVar(1.toByte, DataType.TokenId.id.toByte) + val targetTokenIdStateVar: StateVar = StateVar(2.toByte, DataType.TokenId.id.toByte) + val minSwapAmountStateVar: StateVar = StateVar(3.toByte, DataType.Amount.id.toByte) + val maxSwapAmountStateVar: StateVar = StateVar(4.toByte, DataType.Amount.id.toByte) + val lastUpdateTimeStateVar: StateVar = StateVar(5.toByte, DataType.Timestamp.id.toByte) + val updateGapStateVar: StateVar = StateVar(6.toByte, DataType.Timestamp.id.toByte) + val feeBaseStateVar: StateVar = StateVar(7.toByte, DataType.Amount.id.toByte) + val feeTargetStateVar: StateVar = StateVar(8.toByte, DataType.Amount.id.toByte) + lazy val stateVarSeq = Seq(makerStateVar.arr, baseTokenIdStateVar.arr, targetTokenIdStateVar.arr, + minSwapAmountStateVar.arr, maxSwapAmountStateVar.arr, + lastUpdateTimeStateVar.arr, updateGapStateVar.arr, + feeBaseStateVar.arr, feeTargetStateVar.arr) + lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) + + // State Map + + // Initialization Trigger + + // Deposit Trigger + + // Withdraw Trigger + + // Functions + + // Textual + +} \ No newline at end of file From e2f0b9b55c0f35e9f1fac5d44ca0041a367285df Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 13 Nov 2020 09:45:03 +0800 Subject: [PATCH 128/391] add v stable swap state map --- .../vsys/blockchain/contract/ContractVStableSwap.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index e67415cb9..357b476fa 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -10,7 +10,7 @@ object ContractVStableSwap { Seq(), // Triggers Seq(), // Functions stateVarSeq, // StateVars - Seq(), // StateMaps + stateMapSeq, // StateMaps Seq() // Textual ).explicitGet() @@ -33,6 +33,13 @@ object ContractVStableSwap { lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map + val stateMapBaseTokenBalance = List("baseTokenBalance", "userAddress", "balance") + val stateMapTargetTokenBalance = List("targetTokenBalance", "userAddress", "balance") + val baseTokenBalanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val targetTokenBalanceMap: StateMap = StateMap(1.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + + lazy val stateMapSeq = Seq(baseTokenBalanceMap.arr, targetTokenBalanceMap.arr) + lazy val stateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapBaseTokenBalance, stateMapTargetTokenBalance)) // Initialization Trigger From c83878180f2c98da269a6a942b0b643488507875 Mon Sep 17 00:00:00 2001 From: Icermli Date: Fri, 13 Nov 2020 10:52:22 +0800 Subject: [PATCH 129/391] add RegisterVSwapContractDiffTest skeleton --- .../contract/vswap/VSwapContractGen.scala | 7 +++++++ .../vswap/RegisterVSwapContractDiffTest.scala | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala create mode 100644 src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala new file mode 100644 index 000000000..631be1dbe --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala @@ -0,0 +1,7 @@ +package vsys.blockchain.contract.vswap + + +trait VSwapContractGen { + + +} diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala new file mode 100644 index 000000000..fd9d80ecf --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala @@ -0,0 +1,15 @@ +package vsys.blockchain.state.contract.vswap + +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.contract.vswap.VSwapContractGen +import vsys.blockchain.transaction.TransactionGen + +class RegisterVSwapContractDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with VSwapContractGen { + +} From 4ad84cf2400e7f1f75ec8b0b7c8f91eec1a5cfa0 Mon Sep 17 00:00:00 2001 From: Icermli Date: Sat, 14 Nov 2020 11:13:14 +0800 Subject: [PATCH 130/391] add vswap build test --- .../vswap/RegisterVSwapContractDiffTest.scala | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala index fd9d80ecf..5c5a587cc 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala @@ -1,7 +1,9 @@ package vsys.blockchain.state.contract.vswap +import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.contract.{Contract, ContractGenHelper, ContractVSwap} import vsys.blockchain.contract.vswap.VSwapContractGen import vsys.blockchain.transaction.TransactionGen @@ -12,4 +14,25 @@ class RegisterVSwapContractDiffTest extends PropSpec with TransactionGen with VSwapContractGen { + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val languageCode: String = "vdds" + val languageVersion: Int = 1 + + val preconditionAndBuildVSwapContract: Gen[(Array[Byte], Array[Byte], Seq[Array[Byte]], + Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]])] = for { + langCode <- ContractGenHelper.languageCodeGen(languageCode) + langVer <- ContractGenHelper.languageVersionGen(languageVersion) + init <- Gen.const(ContractVSwap.contract.trigger) + descriptor <- Gen.const(ContractVSwap.contract.descriptor) + stateVar <- Gen.const(ContractVSwap.contract.stateVar) + stateMap <- Gen.const(ContractVSwap.contract.stateMap) + textual <- Gen.const(ContractVSwap.contract.textual) + } yield (langCode, langVer, init, descriptor, stateVar, stateMap, textual) + + property("register v-swap contract build doesn't break invariant"){ + forAll(preconditionAndBuildVSwapContract) { case (langCode, langVer, init, descriptor, stateVar, stateMap, textual) => + Contract.buildContract(langCode, langVer, init, descriptor, stateVar, stateMap, textual) shouldBe an[Right[_, _]] + } + } } From beb91147dcac21570dbda2fb5d4da3a8db55f5fc Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 16 Nov 2020 09:06:59 +0800 Subject: [PATCH 131/391] add v stable swap init trigger --- .../contract/ContractVStableSwap.scala | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 357b476fa..29c43fd9b 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -15,18 +15,19 @@ object ContractVStableSwap { ).explicitGet() // State Var - val stateVarName = List("maker", "baseTokenId", "targetTokenId", "minSwapAmount", "maxSwapAmount", + val stateVarName = List("maker", "baseTokenId", "targetTokenId", "swapStatus", "minSwapAmount", "maxSwapAmount", "lastUpdateTime", "updateGap", "feeBase", "feeTarget") val makerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) val baseTokenIdStateVar: StateVar = StateVar(1.toByte, DataType.TokenId.id.toByte) val targetTokenIdStateVar: StateVar = StateVar(2.toByte, DataType.TokenId.id.toByte) - val minSwapAmountStateVar: StateVar = StateVar(3.toByte, DataType.Amount.id.toByte) - val maxSwapAmountStateVar: StateVar = StateVar(4.toByte, DataType.Amount.id.toByte) - val lastUpdateTimeStateVar: StateVar = StateVar(5.toByte, DataType.Timestamp.id.toByte) - val updateGapStateVar: StateVar = StateVar(6.toByte, DataType.Timestamp.id.toByte) - val feeBaseStateVar: StateVar = StateVar(7.toByte, DataType.Amount.id.toByte) - val feeTargetStateVar: StateVar = StateVar(8.toByte, DataType.Amount.id.toByte) - lazy val stateVarSeq = Seq(makerStateVar.arr, baseTokenIdStateVar.arr, targetTokenIdStateVar.arr, + val swapStatusStateVar: StateVar = StateVar(3.toByte, DataType.Boolean.id.toByte) + val minSwapAmountStateVar: StateVar = StateVar(4.toByte, DataType.Amount.id.toByte) + val maxSwapAmountStateVar: StateVar = StateVar(5.toByte, DataType.Amount.id.toByte) + val lastUpdateTimeStateVar: StateVar = StateVar(6.toByte, DataType.Timestamp.id.toByte) + val updateGapStateVar: StateVar = StateVar(7.toByte, DataType.Timestamp.id.toByte) + val feeBaseStateVar: StateVar = StateVar(8.toByte, DataType.Amount.id.toByte) + val feeTargetStateVar: StateVar = StateVar(9.toByte, DataType.Amount.id.toByte) + lazy val stateVarSeq = Seq(makerStateVar.arr, baseTokenIdStateVar.arr, targetTokenIdStateVar.arr, swapStatusStateVar.arr, minSwapAmountStateVar.arr, maxSwapAmountStateVar.arr, lastUpdateTimeStateVar.arr, updateGapStateVar.arr, feeBaseStateVar.arr, feeTargetStateVar.arr) @@ -42,6 +43,20 @@ object ContractVStableSwap { lazy val stateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapBaseTokenBalance, stateMapTargetTokenBalance)) // Initialization Trigger + val initId: Short = 0 + val initPara: Seq[String] = Seq("baseTokenId", "targetTokenId") ++ + Seq("signer", "swapStatus") + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.TokenId.id.toByte) + val initTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(2.toByte), + cdbvSet ++ Array(makerStateVar.index, 2.toByte), + cdbvSet ++ Array(baseTokenIdStateVar.index, 0.toByte), + cdbvSet ++ Array(targetTokenIdStateVar.index, 1.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + cdbvSet ++ Array(swapStatusStateVar.index, 5.toByte) + ) + lazy val initTrigger: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initTriggerOpcs) + val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) // Deposit Trigger From 08c758ae0619e57bf8d800bd14378c53f494e16e Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 16 Nov 2020 09:10:58 +0800 Subject: [PATCH 132/391] add v stable swap deposit trigger --- .../contract/ContractVStableSwap.scala | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 29c43fd9b..13e63a6e9 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -59,6 +59,36 @@ object ContractVStableSwap { val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) // Deposit Trigger + val depositId: Short = 1 + val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId") ++ + Seq("baseTokenId", "targetTokenId", "isValidTokenId", + "isBaseToken", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock") + val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val depositTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(baseTokenIdStateVar.index, 3.toByte), + cdbvrGet ++ Array(targetTokenIdStateVar.index, 4.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + compareBytesEqual ++ Array(2.toByte, 3.toByte, 6.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(7.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 8.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(11.toByte), + conditionIf ++ Array(6.toByte, 7.toByte), + conditionIf ++ Array(8.toByte, 10.toByte), + assertTrue ++ Array(5.toByte) + ) + lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) + val depositTextualBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) // Withdraw Trigger From 58abe31e0b61a404a2618f45d915f91be5667d38 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 16 Nov 2020 12:33:36 +0800 Subject: [PATCH 133/391] add supersede set swap add liquidity gen --- .../contract/vswap/VSwapContractGen.scala | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala index 631be1dbe..3b8e5fcc0 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala @@ -1,7 +1,95 @@ package vsys.blockchain.contract.vswap +import com.google.common.primitives.Longs +import org.scalacheck.Gen +import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.{Contract, ContractVSwap, DataEntry, DataType} +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.state._ +import vsys.blockchain.transaction.contract.ExecuteContractFunctionTransaction + trait VSwapContractGen { + val supersedeIndex: Short = 0 + val setSwapIndex: Short = 1 + val addLiquidityIndex: Short = 2 + + def vSwapContractGen(): Gen[Contract] = ContractVSwap.contract + + def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + addr <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) + } yield Seq(addr) + + def setSwapDataStackGen(amountADesired: Long, + amountBDesired: Long): Gen[Seq[DataEntry]] = for { + amountADesired <- Gen.const(DataEntry(Longs.toByteArray(amountADesired), DataType.Amount)) + amountBDesired <- Gen.const(DataEntry(Longs.toByteArray(amountBDesired), DataType.Amount)) + } yield Seq(amountADesired, amountBDesired) + + def addLiquidityDataStackGen(amountADesired: Long, + amountBDesired: Long, + amountAMin: Long, + amountBMin: Long, + deadline: Long): Gen[Seq[DataEntry]] = for { + amountADesired <- Gen.const(DataEntry(Longs.toByteArray(amountADesired), DataType.Amount)) + amountBDesired <- Gen.const(DataEntry(Longs.toByteArray(amountBDesired), DataType.Amount)) + amountAMin <- Gen.const(DataEntry(Longs.toByteArray(amountAMin), DataType.Amount)) + amountBMin <- Gen.const(DataEntry(Longs.toByteArray(amountBMin), DataType.Amount)) + deadline <- Gen.const(DataEntry(Longs.toByteArray(deadline), DataType.Timestamp)) + } yield Seq(amountADesired, amountBDesired, amountAMin, amountBMin, deadline) + + def initVSwapDataStackGen(tokenAId: Array[Byte], + tokenBId: Array[Byte], + liquidityTokenId: Array[Byte], + minimumLiquidity: Long): Gen[Seq[DataEntry]] = for { + tokenAId <- Gen.const(DataEntry.create(tokenAId, DataType.TokenId).right.get) + tokenBId <- Gen.const(DataEntry.create(tokenBId, DataType.TokenId).right.get) + liquidityTokenId <- Gen.const(DataEntry.create(liquidityTokenId, DataType.TokenId).right.get) + minimumLiquidity <- Gen.const(DataEntry.create(Longs.toByteArray(minimumLiquidity), DataType.TokenId).right.get) + } yield Seq(tokenAId, tokenBId, liquidityTokenId, minimumLiquidity) + + def supersedeVSwapGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + newAddr: Address, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = supersedeIndex + for { + data: Seq[DataEntry] <- addressDataStackGen(newAddr) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def setSwapVSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + amountADesired: Long, + amountBDesired: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = setSwapIndex + for { + data: Seq[DataEntry] <- setSwapDataStackGen(amountADesired, amountBDesired) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + def addLiquidityVSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + amountADesired: Long, + amountBDesired: Long, + amountAMin: Long, + amountBMin: Long, + deadline: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = addLiquidityIndex + for { + data: Seq[DataEntry] <- addLiquidityDataStackGen(amountADesired, amountBDesired, amountAMin, amountBMin, deadline) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } } From 5d3c8555a2d78faa5dc286196912c5e73f3b0b7e Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 18 Nov 2020 09:50:16 +0800 Subject: [PATCH 134/391] add v stable swap withdraw trigger --- .../contract/ContractVStableSwap.scala | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 13e63a6e9..ce5f9ef29 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -91,6 +91,36 @@ object ContractVStableSwap { val depositTextualBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) // Withdraw Trigger + val withdrawId: Short = 2 + val withdrawPara: Seq[String] = Seq("withdrawer", "amount", "tokenId") ++ + Seq("baseTokenId", "targetTokenId", "isValidTokenId", + "isBaseToken", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock") + val withdrawDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val withdrawTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(baseTokenIdStateVar.index, 3.toByte), + cdbvrGet ++ Array(targetTokenIdStateVar.index, 4.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + compareBytesEqual ++ Array(2.toByte, 3.toByte, 6.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(7.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 8.toByte), + basicConstantGet ++ DataEntry(genFunctionOpcs( + Seq( + cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + ) + ), DataType.OpcBlock).bytes ++ Array(11.toByte), + conditionIf ++ Array(6.toByte, 7.toByte), + conditionIf ++ Array(8.toByte, 10.toByte), + assertTrue ++ Array(5.toByte) + ) + lazy val withdrawTrigger: Array[Byte] = getFunctionBytes(withdrawId, onWithDrawTriggerType, nonReturnType, withdrawDataType, withdrawTriggerOpcs) + val withdrawTextualBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) // Functions From 99aa778047829fda7ea2be35eaabc489cca030e7 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 18 Nov 2020 16:16:40 +0800 Subject: [PATCH 135/391] add removeliquidity and swaptoken --- .../contract/vswap/VSwapContractGen.scala | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala index 3b8e5fcc0..04aeb9fac 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala @@ -14,6 +14,8 @@ trait VSwapContractGen { val supersedeIndex: Short = 0 val setSwapIndex: Short = 1 val addLiquidityIndex: Short = 2 + val removeLiquidityIndex: Short = 3 + val swapTokenForExactBaseTokenIndex: Short = 4 def vSwapContractGen(): Gen[Contract] = ContractVSwap.contract @@ -39,6 +41,24 @@ trait VSwapContractGen { deadline <- Gen.const(DataEntry(Longs.toByteArray(deadline), DataType.Timestamp)) } yield Seq(amountADesired, amountBDesired, amountAMin, amountBMin, deadline) + def removeLiquidityDataStackGen(liquidity: Long, + amountAMin: Long, + amountBMin: Long, + deadline: Long): Gen[Seq[DataEntry]] = for { + liquidity <- Gen.const(DataEntry(Longs.toByteArray(liquidity), DataType.Amount)) + amountAMin <- Gen.const(DataEntry(Longs.toByteArray(amountAMin), DataType.Amount)) + amountBMin <- Gen.const(DataEntry(Longs.toByteArray(amountBMin), DataType.Amount)) + deadline <- Gen.const(DataEntry(Longs.toByteArray(deadline), DataType.Timestamp)) + } yield Seq(liquidity, amountAMin, amountBMin, deadline) + + def swapTokenForExactBaseTokenDataStackGen(amountOut: Long, + amountInMax: Long, + deadline: Long): Gen[Seq[DataEntry]] = for { + amountOut <- Gen.const(DataEntry(Longs.toByteArray(amountOut), DataType.Amount)) + amountInMax <- Gen.const(DataEntry(Longs.toByteArray(amountInMax), DataType.Amount)) + deadline <- Gen.const(DataEntry(Longs.toByteArray(deadline), DataType.Timestamp)) + } yield Seq(amountOut, amountInMax, deadline) + def initVSwapDataStackGen(tokenAId: Array[Byte], tokenBId: Array[Byte], liquidityTokenId: Array[Byte], @@ -92,4 +112,35 @@ trait VSwapContractGen { } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } + + def removeLiquidityVSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + liquidity: Long, + amountAMin: Long, + amountBMin: Long, + deadline: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = removeLiquidityIndex + for { + data: Seq[DataEntry] <- removeLiquidityDataStackGen(liquidity, amountAMin, amountBMin, deadline) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def swapTokenForExactBaseTokenVSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + amountOut: Long, + amountInMax: Long, + deadline: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = swapTokenForExactBaseTokenIndex + for { + data: Seq[DataEntry] <- swapTokenForExactBaseTokenDataStackGen(amountOut, amountInMax, deadline) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } } From cb7458d7653cd61a41d71f2ff9faa935aa816f7e Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 18 Nov 2020 16:30:33 +0800 Subject: [PATCH 136/391] add swap func --- .../contract/vswap/VSwapContractGen.scala | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala index 04aeb9fac..000f3706b 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala @@ -16,6 +16,9 @@ trait VSwapContractGen { val addLiquidityIndex: Short = 2 val removeLiquidityIndex: Short = 3 val swapTokenForExactBaseTokenIndex: Short = 4 + val swapExactTokenForBaseTokenIndex: Short = 5 + val swapTokenForExactTargetTokenIndex: Short = 6 + val swapExactTokenForTargetTokenIndex: Short = 7 def vSwapContractGen(): Gen[Contract] = ContractVSwap.contract @@ -59,6 +62,30 @@ trait VSwapContractGen { deadline <- Gen.const(DataEntry(Longs.toByteArray(deadline), DataType.Timestamp)) } yield Seq(amountOut, amountInMax, deadline) + def swapExactTokenForBaseTokenDataStackGen(amountOutMin: Long, + amountIn: Long, + deadline: Long): Gen[Seq[DataEntry]] = for { + amountOutMin <- Gen.const(DataEntry(Longs.toByteArray(amountOutMin), DataType.Amount)) + amountIn <- Gen.const(DataEntry(Longs.toByteArray(amountIn), DataType.Amount)) + deadline <- Gen.const(DataEntry(Longs.toByteArray(deadline), DataType.Timestamp)) + } yield Seq(amountOutMin, amountIn, deadline) + + def swapTokenForExactTargetTokenDataStackGen(amountOut: Long, + amountInMax: Long, + deadline: Long): Gen[Seq[DataEntry]] = for { + amountOut <- Gen.const(DataEntry(Longs.toByteArray(amountOut), DataType.Amount)) + amountInMax <- Gen.const(DataEntry(Longs.toByteArray(amountInMax), DataType.Amount)) + deadline <- Gen.const(DataEntry(Longs.toByteArray(deadline), DataType.Timestamp)) + } yield Seq(amountOut, amountInMax, deadline) + + def swapExactTokenForTargetTokenDataStackGen(amountOutMin: Long, + amountIn: Long, + deadline: Long): Gen[Seq[DataEntry]] = for { + amountOutMin <- Gen.const(DataEntry(Longs.toByteArray(amountOutMin), DataType.Amount)) + amountIn <- Gen.const(DataEntry(Longs.toByteArray(amountIn), DataType.Amount)) + deadline <- Gen.const(DataEntry(Longs.toByteArray(deadline), DataType.Timestamp)) + } yield Seq(amountOutMin, amountIn, deadline) + def initVSwapDataStackGen(tokenAId: Array[Byte], tokenBId: Array[Byte], liquidityTokenId: Array[Byte], @@ -143,4 +170,49 @@ trait VSwapContractGen { } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } + + def swapExactTokenForBaseTokenVSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + amountOutMin: Long, + amountIn: Long, + deadline: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = swapExactTokenForBaseTokenIndex + for { + data: Seq[DataEntry] <- swapExactTokenForBaseTokenDataStackGen(amountOutMin, amountIn, deadline) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def swapTokenForExactTargetTokenVSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + amountOut: Long, + amountInMax: Long, + deadline: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = swapTokenForExactTargetTokenIndex + for { + data: Seq[DataEntry] <- swapTokenForExactTargetTokenDataStackGen(amountOut, amountInMax, deadline) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def swapExactTokenForTargetTokenVSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + amountOutMin: Long, + amountIn: Long, + deadline: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = swapExactTokenForTargetTokenIndex + for { + data: Seq[DataEntry] <- swapExactTokenForTargetTokenDataStackGen(amountOutMin, amountIn, deadline) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } } From ddbc23454bfef70a1150e43323d6a81cebaef88b Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 23 Nov 2020 15:03:27 +0800 Subject: [PATCH 137/391] add register v swap --- .../vsys/blockchain/contract/Contract.scala | 3 +- .../contract/vswap/VSwapContractGen.scala | 17 +++++++- .../vswap/RegisterVSwapContractDiffTest.scala | 43 ++++++++++++++++++- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index c08c48573..dd475eef0 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -150,7 +150,8 @@ object Contract extends ScorexLogging { !(bytes sameElements ContractPermitted.contractWithoutSplit.bytes.arr) && !(bytes sameElements ContractLock.contract.bytes.arr) && !(bytes sameElements ContractNonFungible.contract.bytes.arr) && - !(bytes sameElements ContractPaymentChannel.contract.bytes.arr)) { + !(bytes sameElements ContractPaymentChannel.contract.bytes.arr) && + !(bytes sameElements ContractVSwap.contract.bytes.arr)) { log.warn(s"Illegal contract ${bytes.mkString(" ")}") false } else if (textualStr.isFailure || diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala index 000f3706b..638c4105a 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala @@ -6,7 +6,8 @@ import vsys.account.{Address, ContractAccount, PrivateKeyAccount} import vsys.blockchain.contract.{Contract, ContractVSwap, DataEntry, DataType} import vsys.blockchain.contract.ContractGenHelper._ import vsys.blockchain.state._ -import vsys.blockchain.transaction.contract.ExecuteContractFunctionTransaction +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} trait VSwapContractGen { @@ -22,6 +23,18 @@ trait VSwapContractGen { def vSwapContractGen(): Gen[Contract] = ContractVSwap.contract + def genesisVSwapGen(rep: PrivateKeyAccount, + ts: Long): Gen[GenesisTransaction] = + GenesisTransaction.create(rep, ENOUGH_AMT, -1, ts).explicitGet() + + def registerVSwapGen(signer: PrivateKeyAccount, + contract: Contract, + dataStack: Seq[DataEntry], + description: String, + fee: Long, + ts: Long): Gen[RegisterContractTransaction] = + RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() + def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { addr <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) } yield Seq(addr) @@ -93,7 +106,7 @@ trait VSwapContractGen { tokenAId <- Gen.const(DataEntry.create(tokenAId, DataType.TokenId).right.get) tokenBId <- Gen.const(DataEntry.create(tokenBId, DataType.TokenId).right.get) liquidityTokenId <- Gen.const(DataEntry.create(liquidityTokenId, DataType.TokenId).right.get) - minimumLiquidity <- Gen.const(DataEntry.create(Longs.toByteArray(minimumLiquidity), DataType.TokenId).right.get) + minimumLiquidity <- Gen.const(DataEntry.create(Longs.toByteArray(minimumLiquidity), DataType.Amount).right.get) } yield Seq(tokenAId, tokenBId, liquidityTokenId, minimumLiquidity) def supersedeVSwapGen(signer: PrivateKeyAccount, diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala index 5c5a587cc..c0d56f758 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala @@ -1,11 +1,19 @@ package vsys.blockchain.state.contract.vswap +import cats.Monoid +import com.google.common.primitives.{Bytes, Ints} import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} -import vsys.blockchain.contract.{Contract, ContractGenHelper, ContractVSwap} +import vsys.account.ContractAccount +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.{Contract, ContractGenHelper, ContractVSwap, DataEntry, DataType} import vsys.blockchain.contract.vswap.VSwapContractGen -import vsys.blockchain.transaction.TransactionGen +import vsys.blockchain.state.diffs.assertDiffAndState +import vsys.blockchain.state._ +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen} +import vsys.blockchain.transaction.contract.RegisterContractTransaction class RegisterVSwapContractDiffTest extends PropSpec with PropertyChecks @@ -35,4 +43,35 @@ class RegisterVSwapContractDiffTest extends PropSpec Contract.buildContract(langCode, langVer, init, descriptor, stateVar, stateMap, textual) shouldBe an[Right[_, _]] } } + + val validContract: Gen[Contract] = vSwapContractGen() + val preconditionsAndRegContractTest: Gen[(GenesisTransaction, RegisterContractTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + genesis <- genesisVSwapGen(master, ts) + contract <- validContract + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + data: Seq[DataEntry] <- initVSwapDataStackGen(tokenId.arr, tokenId.arr, tokenId.arr, 1) + description <- validDescStringGen + create <- registerVSwapGen(master, contract, data, description, fee, ts + 1) + } yield (genesis, create) + + property("register v-swap contract transaction doesn't break invariant") { + forAll(preconditionsAndRegContractTest) { case (genesis, reg: RegisterContractTransaction) => + assertDiffAndState(Seq(TestBlock.create(Seq(genesis))), TestBlock.create(Seq(reg))) { (blockDiff, newState) => + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -reg.transactionFee + totalPortfolioDiff.effectiveBalance shouldBe -reg.transactionFee + val master = reg.proofs.firstCurveProof.explicitGet().publicKey + val contractId = reg.contractId.bytes + val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) + + val (_, masterTxs) = newState.accountTransactionIds(master, 2, 0) + masterTxs.size shouldBe 2 // genesis, reg + newState.contractTokens(contractId) shouldBe 0 + newState.contractContent(contractId) shouldEqual Some((2, reg.id, ContractVSwap.contract)) + + newState.contractInfo(makerKey) shouldEqual Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + } + } + } } From 533b208f5744e4a851ecda585d179673d8ec5594 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 25 Nov 2020 11:18:45 +0800 Subject: [PATCH 138/391] amend languageversion --- .../state/contract/vswap/RegisterVSwapContractDiffTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala index c0d56f758..a2a9cb32a 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/RegisterVSwapContractDiffTest.scala @@ -25,7 +25,7 @@ class RegisterVSwapContractDiffTest extends PropSpec private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) val languageCode: String = "vdds" - val languageVersion: Int = 1 + val languageVersion: Int = 2 val preconditionAndBuildVSwapContract: Gen[(Array[Byte], Array[Byte], Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]])] = for { From 86b920c97317ce3337ddce37f3149a8ceb808f75 Mon Sep 17 00:00:00 2001 From: zl730 Date: Thu, 26 Nov 2020 17:51:46 +0800 Subject: [PATCH 139/391] fix bug in covert opc --- .../state/opcdiffs/BasicOpcDiff.scala | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 71052295d..29104a714 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -73,21 +73,25 @@ object BasicOpcDiff extends OpcDiffer { def convertion(x: DataEntry, t: DataEntry): Either[ValidationError, DataEntry] = t.dataType match { - case DataTypeObj => x.dataType match { - case Int32 | Amount | Timestamp | BigInteger => { + case DataTypeObj =>(x.dataType match { + case Int32 | Amount | Timestamp => Right(x.data) + case BigInteger => Right(x.data.drop(2)) + case _ => Left(ContractUnsupportedOPC) + }) flatMap { bytes => { val to: DataTypeVal[_] = DataTypeObj.deserializer(t.data) to match { - case Int32 => formatResB[Int] (x.data, Int32) - case Amount => formatResB[Long] (x.data, Amount) - case Timestamp => formatResB[Long] (x.data, Timestamp) - case BigInteger => formatResB[BigInt](x.data, BigInteger) + case Int32 => formatResB[Int] (addLeadingZeros(bytes, 4), Int32) + case Amount => formatResB[Long] (addLeadingZeros(bytes, 8), Amount) + case Timestamp => formatResB[Long] (addLeadingZeros(bytes, 8), Timestamp) + case BigInteger => formatResB[BigInt](bytes.dropWhile(i => i == 0), BigInteger) case _ => Left(ContractUnsupportedOPC) } } - case _ => Left(ContractUnsupportedOPC) } case _ => Left(ContractInvalidOPCData) } + def addLeadingZeros(in: Array[Byte], length: Int): Array[Byte] = + new Array[Byte](0.max(length - in.length)) ++ in def concat(x: DataEntry, y: DataEntry): Either[ValidationError, DataEntry] = DataEntry.create(x.data ++ y.data, DataType.ShortBytes) From 5c43f44cedf7ace3144bad1237704f4f81e6cd06 Mon Sep 17 00:00:00 2001 From: zl730 Date: Fri, 27 Nov 2020 12:12:51 +0800 Subject: [PATCH 140/391] limit bytes length --- .../scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 29104a714..371027e11 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -90,13 +90,13 @@ object BasicOpcDiff extends OpcDiffer { } case _ => Left(ContractInvalidOPCData) } - def addLeadingZeros(in: Array[Byte], length: Int): Array[Byte] = - new Array[Byte](0.max(length - in.length)) ++ in + def addLeadingZeros(in: Array[Byte], length: Int): Array[Byte] = + (new Array[Byte](0.max(length - in.length)) ++ in).takeRight(length) def concat(x: DataEntry, y: DataEntry): Either[ValidationError, DataEntry] = DataEntry.create(x.data ++ y.data, DataType.ShortBytes) - def constantGet(constant: Array[Byte]): Either[ValidationError, DataEntry] = + def constantGet(constant: Array[Byte]): Either[ValidationError, DataEntry] = DataEntry.fromBytes(constant) object BasicType extends Enumeration { From d232afd57c07a43bdc1a50c7154735bebbcb5e55 Mon Sep 17 00:00:00 2001 From: zl730 Date: Mon, 30 Nov 2020 11:38:40 +0800 Subject: [PATCH 141/391] fix when value is 0 --- .../scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 371027e11..cb8209154 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -83,7 +83,7 @@ object BasicOpcDiff extends OpcDiffer { case Int32 => formatResB[Int] (addLeadingZeros(bytes, 4), Int32) case Amount => formatResB[Long] (addLeadingZeros(bytes, 8), Amount) case Timestamp => formatResB[Long] (addLeadingZeros(bytes, 8), Timestamp) - case BigInteger => formatResB[BigInt](bytes.dropWhile(i => i == 0), BigInteger) + case BigInteger => formatResB[BigInt](bytes.dropRight(1).dropWhile(i => i == 0) ++ bytes.takeRight(1), BigInteger) case _ => Left(ContractUnsupportedOPC) } } From ae748da300312bc56d56561d3ff007fb03781dc5 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Tue, 8 Dec 2020 11:18:03 +0800 Subject: [PATCH 142/391] test convert opc logic --- .../state/opcdiffs/ConvertOpcDiffTest.scala | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala new file mode 100644 index 000000000..b1913b843 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala @@ -0,0 +1,147 @@ +package vsys.blockchain.state.opcdiffs + +import org.scalatest.{Matchers, PropSpec} +import com.google.common.primitives.{Ints, Longs, Shorts} +import vsys.blockchain.contract.{DataEntry, DataType} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import vsys.blockchain.transaction.ValidationError + +class ConvertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers { + val AmountDataTypeObj = DataEntry(Array(3), DataType.DataTypeObj) + val Int32DataTypeObj = DataEntry(Array(4), DataType.DataTypeObj) + val TimestampDataTypeObj = DataEntry(Array(9), DataType.DataTypeObj) + val BigIntDataTypeObj = DataEntry(Array(14), DataType.DataTypeObj) + + property("test convertions of all numerical types to Amount") { + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(1000).toByteArray.length.toShort) ++ BigInt(1000).toByteArray, DataType.BigInteger), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(1000), DataType.Amount)) + ) + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(1000), DataType.Int32), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(1000), DataType.Amount)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(1000), DataType.Timestamp), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(1000), DataType.Amount)) + ) + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(0), DataType.Amount)) + ) + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(0), DataType.Int32), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(0), DataType.Amount)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(0), DataType.Timestamp), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(0), DataType.Amount)) + ) + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Long.MaxValue).toByteArray.length.toShort) ++ BigInt(Long.MaxValue).toByteArray, DataType.BigInteger), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) + ) + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(Int.MaxValue), DataType.Int32), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(Int.MaxValue), DataType.Amount)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Timestamp), AmountDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) + ) + } + property("test convertions of all numerical types to Int32") { + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(1000).toByteArray.length.toShort) ++ BigInt(1000).toByteArray, DataType.BigInteger), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(1000), DataType.Int32)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(1000), DataType.Amount), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(1000), DataType.Int32)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(1000), DataType.Timestamp), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(1000), DataType.Int32)) + ) + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(0), DataType.Int32)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(0), DataType.Amount), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(0), DataType.Int32)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(0), DataType.Timestamp), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(0), DataType.Int32)) + ) + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Int.MaxValue).toByteArray.length.toShort) ++ BigInt(Int.MaxValue).toByteArray, DataType.BigInteger), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(Int.MaxValue), DataType.Int32)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Int.MaxValue), DataType.Amount), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(Int.MaxValue), DataType.Int32)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Int.MaxValue), DataType.Timestamp), Int32DataTypeObj) should be ( + Right(DataEntry(Ints.toByteArray(Int.MaxValue), DataType.Int32)) + ) + } + property("test convertion of all numerical types to Timestamp") { + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(1000).toByteArray.length.toShort) ++ BigInt(1000).toByteArray, DataType.BigInteger), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(1000), DataType.Timestamp)) + ) + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(1000), DataType.Int32), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(1000), DataType.Timestamp)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(1000), DataType.Amount), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(1000), DataType.Timestamp)) + ) + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(0).toByteArray.length.toShort) ++ BigInt(0).toByteArray, DataType.BigInteger), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(0), DataType.Timestamp)) + ) + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(0), DataType.Int32), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(0), DataType.Timestamp)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(0), DataType.Amount), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(0), DataType.Timestamp)) + ) + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Long.MaxValue).toByteArray.length.toShort) ++ BigInt(Long.MaxValue).toByteArray, DataType.BigInteger), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Timestamp)) + ) + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(Int.MaxValue), DataType.Int32), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(Int.MaxValue), DataType.Timestamp)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Int.MaxValue), DataType.Amount), TimestampDataTypeObj) should be ( + Right(DataEntry(Longs.toByteArray(Int.MaxValue), DataType.Timestamp)) + ) + } + property("test convertion of all numberical types to BigInt") { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(1000), DataType.Amount), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(1000).toByteArray.length.toShort) ++ BigInt(1000).toByteArray, DataType.BigInteger)) + ) + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(1000), DataType.Int32), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(1000).toByteArray.length.toShort) ++ BigInt(1000).toByteArray, DataType.BigInteger)) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(1000), DataType.Timestamp), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(1000).toByteArray.length.toShort) ++ BigInt(1000).toByteArray, DataType.BigInteger)) + ) + } + property("test overflow to Int32") { + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Int.MaxValue + 1).toByteArray.length.toShort) ++ BigInt(Int.MaxValue + 1).toByteArray, DataType.BigInteger), Int32DataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Int.MaxValue + 1), DataType.Amount), Int32DataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Int.MaxValue + 1), DataType.Timestamp), Int32DataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + } + property("test overflow to Amount") { + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Long.MaxValue + 1).toByteArray.length.toShort) ++ BigInt(Long.MaxValue + 1).toByteArray, DataType.BigInteger), AmountDataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue + 1), DataType.Amount), AmountDataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue + 1), DataType.Timestamp), AmountDataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + } + property("test overflow to Timestamp") { + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Long.MaxValue + 1).toByteArray.length.toShort) ++ BigInt(Long.MaxValue + 1).toByteArray, DataType.BigInteger), TimestampDataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue + 1), DataType.Amount), TimestampDataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue + 1), DataType.Timestamp), TimestampDataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + } + +} From c48092a79f540cf34cadbe5515d7fd963b2ddaef Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Mon, 21 Dec 2020 13:18:25 +0800 Subject: [PATCH 143/391] Fix vswap function ids --- .../scala/vsys/blockchain/contract/ContractVSwap.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 86d465b24..acb30a741 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -274,7 +274,7 @@ object ContractVSwap { val addLiquidityTextualBytes: Array[Byte] = textualFunc("addLiquidity", Seq(), addLiquidityPara) // Remove Liquidity - val removeLiquidityId: Short = 2 + val removeLiquidityId: Short = 3 val removeLiquidityPara: Seq[String] = Seq("liquidity", "amountAMin", "amountBMin", "deadline") ++ Seq("caller", "swapStatus", "currentTime", "isValidTime", "reserveA", "reserveB", "bigIntType", "liquidityBigInt", "reserveABigInt", "reserveBBigInt", @@ -362,7 +362,7 @@ object ContractVSwap { ) } - val swapTokenForExactBaseTokenId: Short = 3 + val swapTokenForExactBaseTokenId: Short = 4 val swapTokenForExactBaseTokenPara: Seq[String] = Seq("amountOut", "amountInMax", "deadline") ++ commonSwapPara ++ Seq("amountZero", "isValidAmountOut", "reserveA", "reserveB", @@ -399,7 +399,7 @@ object ContractVSwap { swapDataType, swapTokenForExactBaseTokenFunctionOpcs) val swapTokenForExactBaseTokenTextualBytes: Array[Byte] = textualFunc("swapTokenForExactBaseToken", Seq(), swapTokenForExactBaseTokenPara) - val swapExactTokenForBaseTokenId: Short = 4 + val swapExactTokenForBaseTokenId: Short = 5 val swapExactTokenForBaseTokenPara: Seq[String] = Seq("amountOutMin", "amountIn", "deadline") ++ commonSwapPara ++ Seq("amountZero", "isValidAmountIn", "reserveA", "reserveB", @@ -433,7 +433,7 @@ object ContractVSwap { swapDataType, swapExactTokenForBaseTokenFunctionOpcs) val swapExactTokenForBaseTokenTextualBytes: Array[Byte] = textualFunc("swapExactTokenForBaseToken", Seq(), swapExactTokenForBaseTokenPara) - val swapTokenForExactTargetTokenId: Short = 5 + val swapTokenForExactTargetTokenId: Short = 6 val swapTokenForExactTargetTokenPara: Seq[String] = Seq("amountOut", "amountInMax", "deadline") ++ commonSwapPara ++ Seq("amountZero", "isValidAmountOut", "reserveA", "reserveB", @@ -470,7 +470,7 @@ object ContractVSwap { swapDataType, swapTokenForExactTargetTokenFunctionOpcs) val swapTokenForExactTargetTokenTextualBytes: Array[Byte] = textualFunc("swapTokenForExactTargetToken", Seq(), swapTokenForExactTargetTokenPara) - val swapExactTokenForTargetTokenId: Short = 6 + val swapExactTokenForTargetTokenId: Short = 7 val swapExactTokenForTargetTokenPara: Seq[String] = Seq("amountOutMin", "amountIn", "deadline") ++ commonSwapPara ++ Seq("amountZero", "isValidAmountIn", "reserveA", "reserveB", From 2c955dfda0e99b6b6e00784257748f86e644a609 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Mon, 21 Dec 2020 13:26:00 +0800 Subject: [PATCH 144/391] Fix vswap BigInt constant data entries --- .../blockchain/contract/ContractVSwap.scala | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index acb30a741..3dcf7b3cd 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -190,7 +190,7 @@ object ContractVSwap { compareGreater ++ Array(14.toByte, 15.toByte, 16.toByte), assertTrue ++ Array(16.toByte), basicMinus ++ Array(14.toByte, 15.toByte, 17.toByte), - cdbvrMapGet ++ Array(liquidityBalanceMap.index, 2.toByte, 18.toByte), + cdbvrMapGetOrDefault ++ Array(liquidityBalanceMap.index, 2.toByte, 18.toByte), compareGreater ++ Array(18.toByte, 14.toByte, 19.toByte), assertTrue ++ Array(19.toByte), cdbvMapValMinus ++ Array(liquidityBalanceMap.index, 2.toByte, 18.toByte), @@ -353,10 +353,10 @@ object ContractVSwap { private def swapKValueCheck(updatedReserveA: Byte, updatedReserveB: Byte, value1000: Byte, reservedABigInt: Byte, reservedBBigInt: Byte, updateK: Byte): Seq[Array[Byte]] = { Seq( - basicMultiply ++ Array(updatedReserveA, updatedReserveA, updateK), + basicMultiply ++ Array(updatedReserveA, updatedReserveB, updateK), basicMultiply ++ Array(reservedABigInt, reservedBBigInt, (updateK + 1).toByte), basicMultiply ++ Array(value1000, value1000, (updateK + 2).toByte), - basicMultiply ++ Array((updateK + 1).toByte, (updateK + 1).toByte, (updateK + 3).toByte), + basicMultiply ++ Array((updateK + 1).toByte, (updateK + 2).toByte, (updateK + 3).toByte), compareGreaterEqual ++ Array(updateK, (updateK + 3).toByte, (updateK + 4).toByte), assertTrue ++ Array((updateK + 4).toByte), ) @@ -372,13 +372,13 @@ object ContractVSwap { "amountIn", "isValidAmountIn", "updatedReserveA", "amountInWithOutFee", "updatedReserveB", "updatedK", "KValue", "valueSquare", "oldK", "isValidUpdatedK") val swapTokenForExactBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ commonSwapLoaded(0.toByte) ++ Seq( - basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), + basicConstantGet ++ DataEntry.create(BigInt(1000).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(15.toByte), basicMultiply ++ Array(14.toByte, 15.toByte, 16.toByte), basicMultiply ++ Array(16.toByte, 12.toByte, 17.toByte), - basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(18.toByte), + basicConstantGet ++ DataEntry.create(BigInt(997).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(18.toByte), basicMinus ++ Array(13.toByte, 12.toByte, 19.toByte), basicMultiply ++ Array(19.toByte, 18.toByte, 20.toByte), - basicConstantGet ++ DataEntry(BigInt(1).toByteArray, DataType.BigInteger).bytes ++ Array(21.toByte), + basicConstantGet ++ DataEntry.create(BigInt(1).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(21.toByte), basicDivide ++ Array(17.toByte, 20.toByte, 22.toByte), basicAdd ++ Array(22.toByte, 21.toByte, 23.toByte), basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(24.toByte), @@ -409,9 +409,9 @@ object ContractVSwap { "isValidAmountOut", "subValue", "updatedReserveA", "updatedReserveB", "updatedK", "KValue", "valueSquare","oldK", "isValidUpdatedK") val swapExactTokenForBaseTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ commonSwapLoaded(1.toByte) ++ Seq( - basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), + basicConstantGet ++ DataEntry.create(BigInt(997).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(15.toByte), basicMultiply ++ Array(12.toByte, 15.toByte, 16.toByte), - basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(17.toByte), + basicConstantGet ++ DataEntry.create(BigInt(1000).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(17.toByte), basicMultiply ++ Array(14.toByte, 17.toByte, 18.toByte), basicMultiply ++ Array(13.toByte, 16.toByte, 19.toByte), basicAdd ++ Array(18.toByte, 16.toByte, 20.toByte), @@ -443,13 +443,13 @@ object ContractVSwap { "amountIn", "isValidAmountIn", "updatedReserveB", "amountInWithOutFee", "updatedReserveA", "updatedK", "KValue", "valueSquare", "oldK", "isValidUpdatedK") val swapTokenForExactTargetTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ commonSwapLoaded(0.toByte) ++ Seq( - basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), + basicConstantGet ++ DataEntry.create(BigInt(1000).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(15.toByte), basicMultiply ++ Array(13.toByte, 15.toByte, 16.toByte), basicMultiply ++ Array(16.toByte, 12.toByte, 17.toByte), - basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(18.toByte), + basicConstantGet ++ DataEntry.create(BigInt(997).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(18.toByte), basicMinus ++ Array(14.toByte, 12.toByte, 19.toByte), basicMultiply ++ Array(19.toByte, 18.toByte, 20.toByte), - basicConstantGet ++ DataEntry(BigInt(1).toByteArray, DataType.BigInteger).bytes ++ Array(21.toByte), + basicConstantGet ++ DataEntry.create(BigInt(1).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(21.toByte), basicDivide ++ Array(17.toByte, 20.toByte, 22.toByte), basicAdd ++ Array(22.toByte, 21.toByte, 23.toByte), basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(24.toByte), @@ -480,9 +480,9 @@ object ContractVSwap { "isValidAmountOut", "subValue", "updatedReserveB", "updatedReserveA", "updatedK", "KValue", "valueSquare","oldK", "isValidUpdatedK") val swapExactTokenForTargetTokenFunctionOpcs: Seq[Array[Byte]] = commonSwapFunctionOpcs ++ commonSwapLoaded(1.toByte) ++ Seq( - basicConstantGet ++ DataEntry(BigInt(997).toByteArray, DataType.BigInteger).bytes ++ Array(15.toByte), + basicConstantGet ++ DataEntry.create(BigInt(997).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(15.toByte), basicMultiply ++ Array(12.toByte, 15.toByte, 16.toByte), - basicConstantGet ++ DataEntry(BigInt(1000).toByteArray, DataType.BigInteger).bytes ++ Array(17.toByte), + basicConstantGet ++ DataEntry.create(BigInt(1000).toByteArray, DataType.BigInteger).right.get.bytes ++ Array(17.toByte), basicMultiply ++ Array(13.toByte, 17.toByte, 18.toByte), basicMultiply ++ Array(14.toByte, 16.toByte, 19.toByte), basicAdd ++ Array(18.toByte, 16.toByte, 20.toByte), From da8598da0cd1d56b45cf5213ffd4272bcd740c33 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Mon, 21 Dec 2020 13:28:23 +0800 Subject: [PATCH 145/391] Add If Opc in OpcDiffer --- src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala index c885f0111..1447952c8 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiffer.scala @@ -48,6 +48,7 @@ object OpcDiffer { val ReturnOpc = OpcTypeVal(9, ReturnOpcDiff) val CompareOpc = OpcTypeVal(10, CompareOpcDiff) val BasicOpc = OpcTypeVal(11, BasicOpcDiff) + val IfOpc = OpcTypeVal(12, IfOpcDiff) def fromByte(implicit b: Byte): Option[OpcTypeVal] = Try(OpcType(b).asInstanceOf[OpcTypeVal]).toOption From 35c291b5b0b2e1e7eaea4e4b0fc4fba44b22ef2a Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Mon, 21 Dec 2020 13:55:29 +0800 Subject: [PATCH 146/391] Add registerVSwapDataStackGen --- .../blockchain/contract/vswap/VSwapContractGen.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala index 638c4105a..523efaaa3 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala @@ -27,6 +27,16 @@ trait VSwapContractGen { ts: Long): Gen[GenesisTransaction] = GenesisTransaction.create(rep, ENOUGH_AMT, -1, ts).explicitGet() + def registerVSwapDataStackGen(tokenAId: Array[Byte], + tokenBId: Array[Byte], + liquidityTokenId: Array[Byte], + minimumLiquidity: Long): Gen[Seq[DataEntry]] = for { + tokenAId <- Gen.const(DataEntry(tokenAId, DataType.TokenId)) + tokenBId <- Gen.const(DataEntry(tokenBId, DataType.TokenId)) + liquidityTokenId <- Gen.const(DataEntry(liquidityTokenId, DataType.TokenId)) + minimumLiquidity <- Gen.const(DataEntry(Longs.toByteArray(minimumLiquidity), DataType.Amount)) + } yield Seq(tokenAId, tokenBId, liquidityTokenId, minimumLiquidity) + def registerVSwapGen(signer: PrivateKeyAccount, contract: Contract, dataStack: Seq[DataEntry], From c3812bb482e8ba10d7ba548d76673eb9cc7566f5 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Mon, 21 Dec 2020 16:51:17 +0800 Subject: [PATCH 147/391] Add VSwap Contract OpcDiff Test --- .../contract/vswap/VSwapFunction.scala | 41 ++++++++++ .../vswap/VSwapContractOpcDiffTest.scala | 81 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/vswap/VSwapFunction.scala create mode 100644 src/test/scala/vsys/blockchain/state/contract/vswap/VSwapContractOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunction.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunction.scala new file mode 100644 index 000000000..17478bd27 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunction.scala @@ -0,0 +1,41 @@ +package vsys.blockchain.contract.vswap + +import vsys.blockchain.contract.ContractGen.{basicConstantGet, cdbvSet, getFunctionBytes, loadSigner} +import vsys.blockchain.contract.ContractVSwap._ +import vsys.blockchain.contract.{DataEntry, DataType} + +trait VSwapFunction { + + val initId: Short = 0 + + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.Amount.id.toByte) + val initWrongDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.Amount.id.toByte) + + val initTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(4.toByte), + cdbvSet ++ Array(makerStateVar.index, 4.toByte), + cdbvSet ++ Array(tokenAIdStateVar.index, 0.toByte), + cdbvSet ++ Array(tokenBIdStateVar.index, 1.toByte), + cdbvSet ++ Array(tokenLiquidityIdStateVar.index, 2.toByte), + cdbvSet ++ Array(minimumLiquidityStateVar.index, 3.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + cdbvSet ++ Array(swapStatusStateVar.index, 5.toByte) + ) + + val initWrongTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(4.toByte), + Array(5.toByte, 3.toByte) ++ Array(makerStateVar.index, 4.toByte), + cdbvSet ++ Array(tokenAIdStateVar.index, 0.toByte), + cdbvSet ++ Array(tokenBIdStateVar.index, 1.toByte), + cdbvSet ++ Array(tokenLiquidityIdStateVar.index, 2.toByte), + cdbvSet ++ Array(minimumLiquidityStateVar.index, 3.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + cdbvSet ++ Array(swapStatusStateVar.index, 5.toByte) + ) + + val nonReturnType: Array[Byte] = Array[Byte]() + val onInitTriggerType: Byte = 0 + + lazy val wrongDataTrigger: Seq[Array[Byte]] = Seq(getFunctionBytes(initId, onInitTriggerType, nonReturnType, initWrongDataType, initTriggerOpcs)) + lazy val wrongOpcTrigger: Seq[Array[Byte]] = Seq(getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initWrongTriggerOpcs)) +} diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/VSwapContractOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/VSwapContractOpcDiffTest.scala new file mode 100644 index 000000000..3e98ef8f0 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/VSwapContractOpcDiffTest.scala @@ -0,0 +1,81 @@ +package vsys.blockchain.state.contract.vswap + +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry} +import vsys.blockchain.contract.ContractVSwap._ +import vsys.utils.serialization.Deser +import com.google.common.primitives.{Bytes, Ints} +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount +import vsys.blockchain.contract.vswap.{VSwapContractGen, VSwapFunction} +import vsys.blockchain.state._ +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidOPCData} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.blockchain.transaction.TransactionGen + +class VSwapContractOpcDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with VSwapContractGen + with VSwapFunction { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val regWrongOpcFunContract: Gen[Contract] = + Gen.const(Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + wrongOpcTrigger, + Seq(supersedeFunc, setSwapFunc, addLiquidityFunc, removeLiquidityFunc, swapTokenForExactBaseTokenFunc, + swapExactTokenForBaseTokenFunc, swapTokenForExactTargetTokenFunc, swapExactTokenForTargetTokenFunc), + stateVarSeq, stateMapSeq, Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual)).explicitGet()) + + val regWrongDataContract: Gen[Contract] = + Gen.const(Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + wrongDataTrigger, + Seq(supersedeFunc, setSwapFunc, addLiquidityFunc, removeLiquidityFunc, swapTokenForExactBaseTokenFunc, + swapExactTokenForBaseTokenFunc, swapTokenForExactTargetTokenFunc, swapExactTokenForTargetTokenFunc), + stateVarSeq, stateMapSeq, Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual)).explicitGet()) + + val validContract: Gen[Contract] = vSwapContractGen() + val preconditionsAndRegContractWrongFun: Gen[(RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + validContract <- validContract + wrongOpcContract <- regWrongOpcFunContract + wrongDataContract <- regWrongDataContract + + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + data: Seq[DataEntry] <- initVSwapDataStackGen(tokenId.arr, tokenId.arr, tokenId.arr, 1) + description <- validDescStringGen + validCreate <- registerVSwapGen(master, validContract, data, description, fee, ts + 1) + wrongOpcCreate <- registerVSwapGen(master, wrongOpcContract, data, description, fee + 10000000000L, ts+3) + wrongDataCreate <- registerVSwapGen(master, wrongDataContract, data, description, fee + 10000000000L, ts+3) + } yield (validCreate, wrongOpcCreate, wrongDataCreate) + + property("register contract transaction cannot pass due to wrong opcode"){ + forAll(preconditionsAndRegContractWrongFun) { case (validCreate, wrongOpcCreate, _) => + assertOpcFuncDifferEi(2, None, validCreate) { opcFunDiffEi => + opcFunDiffEi shouldBe an[Right[_, _]] + } + + assertOpcFuncDifferEi(2, None, wrongOpcCreate) { opcFunDiffEi => + opcFunDiffEi shouldBe Left(ContractInvalidOPCData) + } + } + } + + property("register contract transaction cannot pass due to wrong list of parameters"){ + forAll(preconditionsAndRegContractWrongFun) { case (_, _, wrongDataCreate) => + assertOpcFuncDifferEi(2, None, wrongDataCreate) { opcFunDiffEi => + opcFunDiffEi shouldBe Left(ContractDataTypeMismatch) + } + } + } +} + + + + From f1217893a6e4deecff4c2fe500d9039dd764fcfb Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Tue, 22 Dec 2020 10:04:56 +0800 Subject: [PATCH 148/391] Add helper functions for vswap unit test --- .../vswap/VSwapFunctionHelperGen.scala | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala new file mode 100644 index 000000000..523509821 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala @@ -0,0 +1,101 @@ +package vsys.blockchain.contract.vswap + +import com.google.common.primitives.{Longs, Ints} +import org.scalacheck.Gen +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.account.{ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.{DataEntry, DataType} +import vsys.blockchain.contract.token.TokenContractGen +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { + + def registerToken(totalSupply: Long, + unity: Long, + desc: String, + user: PrivateKeyAccount, + fee: Long, + timestamp: Long): Gen[RegisterContractTransaction] = for { + initTokenDataStack: Seq[DataEntry] <- initTokenDataStackGen(totalSupply, unity, desc) + description <- validDescStringGen + tokenContract <- tokenContractGen(false) + regTokenContract <- registerTokenGen(user, tokenContract, initTokenDataStack, description, fee, timestamp) + } yield regTokenContract + + def issueToken(issueAmount: Long, + user: PrivateKeyAccount, + contractId: ContractAccount, + fee: Long, + timestamp: Long): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issueToken <- issueTokenGen(user, contractId, issueAmount, attach, fee, timestamp) + } yield issueToken + + def depositToken(sender: Array[Byte], + contract: Array[Byte], + amount: Long, + user: PrivateKeyAccount, + contractId: ContractAccount, + fee: Long, + timestamp: Long + ): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + depositTokenData = Seq(sender, contract, Longs.toByteArray(amount)) + depositTokenDataType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + depositToken <- depositTokenGen(user, contractId, false, depositTokenData, depositTokenDataType, attach, fee, timestamp) + } yield depositToken + + def createABLiquidityTokenAndInitVSwap(totalSupplyA: Long, + unityA: Long, + issueAmountA: Long, + totalSupplyB: Long, + unityB: Long, + issueAmountB: Long, + liquidityTotalSupply: Long, + liquidityUnity: Long, + minimumLiquidity: Long, + tokenADepositAmount: Long, + tokenBDepositAmount: Long): Gen[(GenesisTransaction, GenesisTransaction, + PrivateKeyAccount, PrivateKeyAccount, RegisterContractTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, Long, Long, Array[Byte])] = for { + (master, ts, fee) <- basicContractTestGen() + genesis <- genesisVSwapGen(master, ts) + user <- accountGen + genesis2 <- genesisVSwapGen(user, ts) + vSwapContract <- vSwapContractGen() + // register token A + regTokenAContract <- registerToken(totalSupplyA, unityA, "init", master, fee + 10000000000L, ts) + tokenAContractId = regTokenAContract.contractId + tokenAId = tokenIdFromBytes(tokenAContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register token B + regTokenBContract <- registerToken(totalSupplyB, unityB, "init", master, fee + 10000000000L, ts + 1) + tokenBContractId = regTokenBContract.contractId + tokenBId = tokenIdFromBytes(tokenBContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register liquidity token + regLiquidityTokenContract <- registerToken(liquidityTotalSupply, liquidityUnity, "init", master, fee + 10000000000L, ts + 2) + liquidityTokenContractId = regLiquidityTokenContract.contractId + liquidityTokenId = tokenIdFromBytes(liquidityTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register VSwap contract + description <- validDescStringGen + initVSwapDataStack: Seq[DataEntry] <- registerVSwapDataStackGen(tokenAId.arr, tokenBId.arr, liquidityTokenId.arr, minimumLiquidity) + regVSwapContract <- registerVSwapGen(master, vSwapContract, initVSwapDataStack, description, fee + 10000000000L, ts + 3) + vSwapContractId = regVSwapContract.contractId + // issue token A + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issueTokenA <- issueToken(issueAmountA, master, tokenAContractId, fee, ts + 4) + // issue token B + issueTokenB <- issueToken(issueAmountB, master, tokenBContractId, fee, ts + 5) + // issue liquidity token, always issue the entire supply of liquidity tokens + issueLiquidityToken <- issueToken(liquidityTotalSupply, master, liquidityTokenContractId, fee, ts + 6) + // deposit all issued tokens into swap contract, always deposit the entire supply of liquidity tokens + depositTokenA <- depositToken(master.toAddress.bytes.arr, vSwapContractId.bytes.arr, tokenADepositAmount, master, tokenAContractId, fee + 10000000000L, ts + 7) + depositTokenB <- depositToken(master.toAddress.bytes.arr, vSwapContractId.bytes.arr, tokenBDepositAmount, master, tokenBContractId, fee + 10000000000L, ts + 8) + depositLiquidity <- depositToken(master.toAddress.bytes.arr, vSwapContractId.bytes.arr, liquidityTotalSupply, master, tokenAContractId, fee + 10000000000L, ts + 9) + } yield (genesis, genesis2, master, user, regTokenAContract, regTokenBContract, regLiquidityTokenContract, regVSwapContract, + issueTokenA, issueTokenB, issueLiquidityToken, depositTokenA, depositTokenB, depositLiquidity, fee, ts, attach) + +} From 1bc840125c5095d4b0a95e180a9156f74ad21cec Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Tue, 22 Dec 2020 10:22:44 +0800 Subject: [PATCH 149/391] remove unused imports and fix clashing function names --- .../contract/vswap/VSwapFunctionHelperGen.scala | 10 ++++++++-- .../contract/vswap/VSwapContractOpcDiffTest.scala | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala index 523509821..a9f0d2220 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala @@ -1,9 +1,9 @@ package vsys.blockchain.contract.vswap -import com.google.common.primitives.{Longs, Ints} +import com.google.common.primitives.{Ints, Longs} import org.scalacheck.Gen import vsys.account.ContractAccount.tokenIdFromBytes -import vsys.account.{ContractAccount, PrivateKeyAccount} +import vsys.account.{Address, ContractAccount, PrivateKeyAccount} import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.token.TokenContractGen import vsys.blockchain.contract.ContractGenHelper._ @@ -12,6 +12,12 @@ import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { + override val supersedeIndex: Short = 0 + + override def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + addr <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) + } yield Seq(addr) + def registerToken(totalSupply: Long, unity: Long, desc: String, diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/VSwapContractOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/VSwapContractOpcDiffTest.scala index 3e98ef8f0..94de96c0d 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/VSwapContractOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/VSwapContractOpcDiffTest.scala @@ -4,7 +4,7 @@ import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry} import vsys.blockchain.contract.ContractVSwap._ import vsys.utils.serialization.Deser -import com.google.common.primitives.{Bytes, Ints} +import com.google.common.primitives.Ints import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} From 00880d08d02b2b89b1617e729bcf451ea5d49828 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Tue, 22 Dec 2020 10:31:07 +0800 Subject: [PATCH 150/391] remove duplicated function --- .../blockchain/contract/vswap/VSwapContractGen.scala | 10 ---------- .../contract/vswap/VSwapFunctionHelperGen.scala | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala index 523efaaa3..638c4105a 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapContractGen.scala @@ -27,16 +27,6 @@ trait VSwapContractGen { ts: Long): Gen[GenesisTransaction] = GenesisTransaction.create(rep, ENOUGH_AMT, -1, ts).explicitGet() - def registerVSwapDataStackGen(tokenAId: Array[Byte], - tokenBId: Array[Byte], - liquidityTokenId: Array[Byte], - minimumLiquidity: Long): Gen[Seq[DataEntry]] = for { - tokenAId <- Gen.const(DataEntry(tokenAId, DataType.TokenId)) - tokenBId <- Gen.const(DataEntry(tokenBId, DataType.TokenId)) - liquidityTokenId <- Gen.const(DataEntry(liquidityTokenId, DataType.TokenId)) - minimumLiquidity <- Gen.const(DataEntry(Longs.toByteArray(minimumLiquidity), DataType.Amount)) - } yield Seq(tokenAId, tokenBId, liquidityTokenId, minimumLiquidity) - def registerVSwapGen(signer: PrivateKeyAccount, contract: Contract, dataStack: Seq[DataEntry], diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala index a9f0d2220..91f87ca4f 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala @@ -87,7 +87,7 @@ trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { liquidityTokenId = tokenIdFromBytes(liquidityTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() // register VSwap contract description <- validDescStringGen - initVSwapDataStack: Seq[DataEntry] <- registerVSwapDataStackGen(tokenAId.arr, tokenBId.arr, liquidityTokenId.arr, minimumLiquidity) + initVSwapDataStack: Seq[DataEntry] <- initVSwapDataStackGen(tokenAId.arr, tokenBId.arr, liquidityTokenId.arr, minimumLiquidity) regVSwapContract <- registerVSwapGen(master, vSwapContract, initVSwapDataStack, description, fee + 10000000000L, ts + 3) vSwapContractId = regVSwapContract.contractId // issue token A From 19b8640f5281f2986bc05a1260c83406d4547faa Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Tue, 22 Dec 2020 15:38:47 +0800 Subject: [PATCH 151/391] fix helper function bugs --- .../vswap/VSwapFunctionHelperGen.scala | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala index 91f87ca4f..6d5f3c329 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala @@ -18,10 +18,10 @@ trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { addr <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) } yield Seq(addr) - def registerToken(totalSupply: Long, + def registerToken(user: PrivateKeyAccount, + totalSupply: Long, unity: Long, desc: String, - user: PrivateKeyAccount, fee: Long, timestamp: Long): Gen[RegisterContractTransaction] = for { initTokenDataStack: Seq[DataEntry] <- initTokenDataStackGen(totalSupply, unity, desc) @@ -30,20 +30,20 @@ trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { regTokenContract <- registerTokenGen(user, tokenContract, initTokenDataStack, description, fee, timestamp) } yield regTokenContract - def issueToken(issueAmount: Long, - user: PrivateKeyAccount, + def issueToken(user: PrivateKeyAccount, contractId: ContractAccount, + issueAmount: Long, fee: Long, timestamp: Long): Gen[ExecuteContractFunctionTransaction] = for { attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) issueToken <- issueTokenGen(user, contractId, issueAmount, attach, fee, timestamp) } yield issueToken - def depositToken(sender: Array[Byte], + def depositToken(user: PrivateKeyAccount, + contractId: ContractAccount, + sender: Array[Byte], contract: Array[Byte], amount: Long, - user: PrivateKeyAccount, - contractId: ContractAccount, fee: Long, timestamp: Long ): Gen[ExecuteContractFunctionTransaction] = for { @@ -53,6 +53,19 @@ trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { depositToken <- depositTokenGen(user, contractId, false, depositTokenData, depositTokenDataType, attach, fee, timestamp) } yield depositToken + def withdrawToken(user: PrivateKeyAccount, + contractId: ContractAccount, + contract: Array[Byte], + sender: Array[Byte], + amount: Long, + fee: Long, + timestamp: Long): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + withdrawTokenData = Seq(contract, sender, Longs.toByteArray(amount)) + withdrawTokenDataType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + withdrawToken <- withdrawTokenGen(user, contractId, false, withdrawTokenData, withdrawTokenDataType, attach, fee, timestamp) + } yield withdrawToken + def createABLiquidityTokenAndInitVSwap(totalSupplyA: Long, unityA: Long, issueAmountA: Long, @@ -74,15 +87,15 @@ trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { genesis2 <- genesisVSwapGen(user, ts) vSwapContract <- vSwapContractGen() // register token A - regTokenAContract <- registerToken(totalSupplyA, unityA, "init", master, fee + 10000000000L, ts) + regTokenAContract <- registerToken(master, totalSupplyA, unityA, "init", fee + 10000000000L, ts) tokenAContractId = regTokenAContract.contractId tokenAId = tokenIdFromBytes(tokenAContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() // register token B - regTokenBContract <- registerToken(totalSupplyB, unityB, "init", master, fee + 10000000000L, ts + 1) + regTokenBContract <- registerToken(master, totalSupplyB, unityB, "init", fee + 10000000000L, ts + 1) tokenBContractId = regTokenBContract.contractId tokenBId = tokenIdFromBytes(tokenBContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() // register liquidity token - regLiquidityTokenContract <- registerToken(liquidityTotalSupply, liquidityUnity, "init", master, fee + 10000000000L, ts + 2) + regLiquidityTokenContract <- registerToken(master, liquidityTotalSupply, liquidityUnity, "init", fee + 10000000000L, ts + 2) liquidityTokenContractId = regLiquidityTokenContract.contractId liquidityTokenId = tokenIdFromBytes(liquidityTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() // register VSwap contract @@ -92,16 +105,15 @@ trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { vSwapContractId = regVSwapContract.contractId // issue token A attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) - issueTokenA <- issueToken(issueAmountA, master, tokenAContractId, fee, ts + 4) + issueTokenA <- issueToken(master, tokenAContractId, issueAmountA, fee, ts + 4) // issue token B - issueTokenB <- issueToken(issueAmountB, master, tokenBContractId, fee, ts + 5) + issueTokenB <- issueToken(master, tokenBContractId, issueAmountB, fee, ts + 5) // issue liquidity token, always issue the entire supply of liquidity tokens - issueLiquidityToken <- issueToken(liquidityTotalSupply, master, liquidityTokenContractId, fee, ts + 6) + issueLiquidityToken <- issueToken(master, liquidityTokenContractId, liquidityTotalSupply, fee, ts + 6) // deposit all issued tokens into swap contract, always deposit the entire supply of liquidity tokens - depositTokenA <- depositToken(master.toAddress.bytes.arr, vSwapContractId.bytes.arr, tokenADepositAmount, master, tokenAContractId, fee + 10000000000L, ts + 7) - depositTokenB <- depositToken(master.toAddress.bytes.arr, vSwapContractId.bytes.arr, tokenBDepositAmount, master, tokenBContractId, fee + 10000000000L, ts + 8) - depositLiquidity <- depositToken(master.toAddress.bytes.arr, vSwapContractId.bytes.arr, liquidityTotalSupply, master, tokenAContractId, fee + 10000000000L, ts + 9) + depositTokenA <- depositToken(master, tokenAContractId, master.toAddress.bytes.arr, vSwapContractId.bytes.arr, tokenADepositAmount, fee + 10000000000L, ts + 7) + depositTokenB <- depositToken(master, tokenBContractId, master.toAddress.bytes.arr, vSwapContractId.bytes.arr, tokenBDepositAmount, fee + 10000000000L, ts + 8) + depositLiquidity <- depositToken(master, liquidityTokenContractId, master.toAddress.bytes.arr, vSwapContractId.bytes.arr, liquidityTotalSupply, fee + 10000000000L, ts + 9) } yield (genesis, genesis2, master, user, regTokenAContract, regTokenBContract, regLiquidityTokenContract, regVSwapContract, issueTokenA, issueTokenB, issueLiquidityToken, depositTokenA, depositTokenB, depositLiquidity, fee, ts, attach) - } From 49d58c8d278c1ed1d1d6d37ba3ff0d5b0c5c09fe Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Tue, 22 Dec 2020 15:39:00 +0800 Subject: [PATCH 152/391] add valid diff tests --- .../vswap/ExecuteVSwapValidDiffTest.scala | 340 ++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala new file mode 100644 index 000000000..3379e5a0f --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala @@ -0,0 +1,340 @@ +package vsys.blockchain.state.contract.vswap + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} +import vsys.blockchain.contract.vswap.{VSwapContractGen, VSwapFunctionHelperGen} +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.contract._ +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} + +class ExecuteVSwapValidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with TokenContractGen + with SystemContractGen + with VSwapContractGen + with VSwapFunctionHelperGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndVSwapDepositAndWithdrawLiquidityTokens: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + // register 3 tokens and VSwap contract, then deposit all 3 tokens into contract + // the function will issue and deposit the entire supply of liquidity tokens + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 1000, // total supply of token A + 1, // unity of token A + 1000, // issue amount of token A + 1000, // total supply of token B + 1, // unity of token B + 1000, // issue amount of token B + 1000, // total supply of liquidity token + 1000, // unity of liquidity token + 10, // minimum liquidity + 10, // deposit amount of token A + 10) // deposit amount of token B + //withdraw tokens + withdrawTokenA <- withdrawToken(master, regTokenA.contractId, regVSwap.contractId.bytes.arr, master.toAddress.bytes.arr, 10L, fee, ts + 10) + withdrawTokenB <- withdrawToken(master, regTokenB.contractId, regVSwap.contractId.bytes.arr, master.toAddress.bytes.arr, 10L, fee, ts + 11) + withdrawLiquidity <- withdrawToken(master, regLiquidity.contractId, regVSwap.contractId.bytes.arr, master.toAddress.bytes.arr, 10L, fee, ts + 12) + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, + withdrawTokenA, withdrawTokenB, withdrawLiquidity) + + property("vswap able to withdraw balance") { + forAll(preconditionsAndVSwapDepositAndWithdrawLiquidityTokens) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, withdrawA: ExecuteContractFunctionTransaction, withdrawB: ExecuteContractFunctionTransaction, + withdrawLiquidity: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), + TestBlock.createWithTxStatus(withdrawLiquidity.timestamp, Seq(withdrawLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVSwapSetSwap: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 1000, // totalSupplyA + 1, // unityA + 1000, // issueAmountA + 1000, // totalSupplyB + 1, //unityB + 1000, // issueAmountB + 1000, // liquidityTotalSupply + 1000, // liquidityUnity + 9, // minimumLiquidity + 100, // tokenADepositAmount + 100) // tokenBDepositAmount + // set swap + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 10L, 10L, attach, fee + 10000000000L, ts + 10) + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap) + + property("vswap able to setswap") { + forAll(preconditionsAndVSwapSetSwap) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositLiquidity.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(setSwap), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVSwapAddLiquidity: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 10000, // totalSupplyA + 1, // unityA + 10000, // issueAmountA + 10000, // totalSupplyB + 1, // unityB + 10000, // issueAmountB + 10000, // liquidityTotalSupply + 1000, // liquidityUnity + 10, // minimumLiquidity + 2000, // tokenADepositAmount + 2000) // tokenBDepositAmount + + // set swap -> amountADesired, amountBDesired + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts + 10) + + // add liquidity -> amountADesired, amountBDesired, amountAMin, amountBMin + addLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 1000L, 1000L, 900L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 11) + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, addLiquidity) + + property("vswap able to add liquidity") { + forAll(preconditionsAndVSwapAddLiquidity) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, addLiquidity: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(addLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVSwapRemoveLiquidity: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 10000, // totalSupplyA + 1, // unityA + 10000, // issueAmountA + 10000, // totalSupplyB + 1, // unityB + 10000, // issueAmountB + 10000, // liquidityTotalSupply + 1000, // liquidityUnity + 10, // minimumLiquidity + 2000, // tokenADepositAmount + 2000) // tokenBDepositAmount + + // set swap -> amountADesired, amountBDesired + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts + 10) + + // add liquidity -> amountADesired, amountBDesired, amountAMin, amountBMin + addLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 1000L, 1000L, 900L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 11) + + // remove liquidity -> liquidity, amountAMin, amountBMin + removeLiquidity <- removeLiquidityVSwapGen(master, regVSwap.contractId, 1000L, 1000L, 1000L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 12) + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, addLiquidity, removeLiquidity) + + property("vswap able to remove liquidity") { + forAll(preconditionsAndVSwapRemoveLiquidity) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, addLiquidity: ExecuteContractFunctionTransaction, + removeLiquidity: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap, addLiquidity))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(removeLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVSwapSwapTokenForExactBaseToken: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 10000, // totalSupplyA + 1, // unityA + 10000, // issueAmountA + 10000, // totalSupplyB + 1, // unityB + 10000, // issueAmountB + 10000, // liquidityTotalSupply + 1000, // liquidityUnity + 10, // minimumLiquidity + 2000, // tokenADepositAmount + 2000) // tokenBDepositAmount + + // set swap -> amountADesired, amountBDesired + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts + 10) + + // swap for 100 base tokens -> amountOut, amountInMax, deadline + swapTokenForExactBaseToken <- swapTokenForExactBaseTokenVSwapGen(master, regVSwap.contractId, 100L, 112L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 11) + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, swapTokenForExactBaseToken) + + property("vswap able to swap tokens for exact base token") { + forAll(preconditionsAndVSwapSwapTokenForExactBaseToken) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, swapTokenForExactBaseToken: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapTokenForExactBaseToken), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVSwapSwapExactTokenForBaseToken: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 10000, // totalSupplyA + 1, // unityA + 10000, // issueAmountA + 10000, // totalSupplyB + 1, // unityB + 10000, // issueAmountB + 10000, // liquidityTotalSupply + 1000, // liquidityUnity + 10, // minimumLiquidity + 2000, // tokenADepositAmount + 2000) // tokenBDepositAmount + + // set swap -> amountADesired, amountBDesired + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts + 10) + + // swap 100 tokens for base tokens -> amountOutMin, amountIn, deadline + swapExactTokenForBaseToken <- swapExactTokenForBaseTokenVSwapGen(master, regVSwap.contractId, 90L, 100L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 11) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, swapExactTokenForBaseToken) + + property("vswap able to swap exact token for base token") { + forAll(preconditionsAndVSwapSwapExactTokenForBaseToken) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, swapExactTokenForBaseToken: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapExactTokenForBaseToken), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVSwapSwapTokenForExactTargetToken: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 10000, // totalSupplyA + 1, // unityA + 10000, // issueAmountA + 10000, // totalSupplyB + 1, // unityB + 10000, // issueAmountB + 10000, // liquidityTotalSupply + 1000, // liquidityUnity + 10, // minimumLiquidity + 2000, // tokenADepositAmount + 2000) // tokenBDepositAmount + + // set swap -> amountADesired, amountBDesired + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts + 10) + + // swap for 100 target tokens + swapTokenForExactTargetToken <- swapTokenForExactTargetTokenVSwapGen(master, regVSwap.contractId, 100L, 112L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 11) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, swapTokenForExactTargetToken) + + property("vswap able to swap token for exact target token") { + forAll(preconditionsAndVSwapSwapTokenForExactTargetToken) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, swapTokenForExactTargetToken: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapTokenForExactTargetToken), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVSwapSwapExactTokenForTargetToken: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 10000, // totalSupplyA + 1, // unityA + 10000, // issueAmountA + 10000, // totalSupplyB + 1, // unityB + 10000, // issueAmountB + 10000, // liquidiityTotalSupply + 1000, // liquidityUnity + 10, // minimumLiquidity + 2000, // tokenADepositAmount + 2000) // tokenBDepositAmount + + // set swap -> amountADesired, amountBDesired + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts + 10) + + // swap 100 tokens for target token -> amountOutMin, amountIn + swapExactTokenForTargetToken <- swapExactTokenForTargetTokenVSwapGen(master, regVSwap.contractId, 90L, 100L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 11) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, swapExactTokenForTargetToken) + + property("vswap able to swap exact token for target token") { + forAll(preconditionsAndVSwapSwapExactTokenForTargetToken) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, swapExactTokenForTargetToken: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapExactTokenForTargetToken), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } +} \ No newline at end of file From e6dc65269ffb435a286f509293c83e8417b36730 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 22 Dec 2020 17:39:40 +0800 Subject: [PATCH 153/391] Add VSwap Contract Invalid Unit Test --- .../vswap/ExecuteVSwapInvalidDiffTest.scala | 390 ++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala new file mode 100644 index 000000000..a23793845 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala @@ -0,0 +1,390 @@ +package vsys.blockchain.state.contract.vswap + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} +import vsys.blockchain.contract.vswap.{VSwapContractGen, VSwapFunctionHelperGen} +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.contract._ +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.state._ + +class ExecuteVSwapInvalidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with TokenContractGen + with SystemContractGen + with VSwapContractGen + with VSwapFunctionHelperGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndVSwapDepositAndWithdrawLiquidityTokens: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, _, _, _, regLiquidity, regVSwap, _, _, issueLiquidity, _, _, depositLiquidity, fee, ts, attach) <- createABLiquidityTokenAndInitVSwap(1000, 1, 1000, 1000, 1, 1000, + 1000, 1000,10, 100, 100) + withdrawLiquidity <- withdrawToken(master, regLiquidity.contractId, regVSwap.contractId.bytes.arr, master.toAddress.bytes.arr, 100L, fee, ts + 12) + withdrawInvalidLiquidity <- withdrawToken(master, regLiquidity.contractId, regVSwap.contractId.bytes.arr, master.toAddress.bytes.arr, 2000L, fee, ts + 12) + } yield (genesis, genesis2, regLiquidity, regVSwap, issueLiquidity, depositLiquidity, withdrawLiquidity, withdrawInvalidLiquidity) + + // withdraw liquidity tokens, withdraw token A and B have been local tested successfully + property("withdraw liquidity tokens more than depositing in vswap contract") { + forAll(preconditionsAndVSwapDepositAndWithdrawLiquidityTokens) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueLiquidity: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, withdrawLiquidity: ExecuteContractFunctionTransaction, withdrawInvalidLiquidity: ExecuteContractFunctionTransaction) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositLiquidity.timestamp, Seq(regLiquidity, regVSwap, issueLiquidity, depositLiquidity))), + TestBlock.createWithTxStatus(withdrawLiquidity.timestamp, Seq(withdrawLiquidity), TransactionStatus.Success)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositLiquidity.timestamp, Seq(regLiquidity, regVSwap, issueLiquidity, depositLiquidity))), + TestBlock.createWithTxStatus(withdrawInvalidLiquidity.timestamp, Seq(withdrawInvalidLiquidity), TransactionStatus.ContractTokenBalanceInsufficient)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient + } + } + } + + val preconditionsAndVSwapSetSwap: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, _, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap(1000, 1, 1000, 1000, 1, 1000, 1000, 1000,9, 100, 100) + + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 10L, 10L, attach, fee + 10000000000L, ts) + setInvalidSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 10L, attach, fee + 10000000000L, ts) + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, setInvalidSwap) + + // set swap token A more than deposit, set swap token B more than deposit has been local tested successfully + property("set swap more than deposit") { + forAll(preconditionsAndVSwapSetSwap) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, setInvalidSwap: ExecuteContractFunctionTransaction) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositLiquidity.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(setSwap), TransactionStatus.Success)) { (blockDiff) => + blockDiff.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositLiquidity.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), + TestBlock.createWithTxStatus(setInvalidSwap.timestamp, Seq(setInvalidSwap), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + } + } + + val preconditionsAndVSwapAddLiquidity: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap(10000, 1, 10000, 10000, 1, 10000, + 10000, 1000,10, 3000, 3000) + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts) + + addLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 2000L, 2000L, 900L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + addInvalidLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 3000L, 2000L, 900L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + addInvalidLiquidity2 <- addLiquidityVSwapGen(master, regVSwap.contractId, 2000L, 2000L, 9000L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + addInvalidLiquidity3 <- addLiquidityVSwapGen(master, regVSwap.contractId, 2000L, 2000L, 900L, 900L, ts - 1000000000000L, attach, fee + 10000000000L, ts) + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, addLiquidity, addInvalidLiquidity, addInvalidLiquidity2, addInvalidLiquidity3) + + property("unable to add liquidity") { + forAll(preconditionsAndVSwapAddLiquidity) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, addLiquidity: ExecuteContractFunctionTransaction, + addInvalidLiquidity: ExecuteContractFunctionTransaction, addInvalidLiquidity2: ExecuteContractFunctionTransaction, addInvalidLiquidity3: ExecuteContractFunctionTransaction) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(addLiquidity.timestamp, Seq(addLiquidity), TransactionStatus.Success)) { (blockDiff) => + blockDiff.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // add liquidity more than tokenADepositAmount, add liquidity more than tokenBDepositAmount has been locally tested successfully + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(addInvalidLiquidity.timestamp, Seq(addInvalidLiquidity), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // add liquidity less than amountAMin, add liquidity less than amountBMin has been locally tested successfully + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(addInvalidLiquidity2.timestamp, Seq(addInvalidLiquidity2), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // add liquidity with a wrong deadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(addInvalidLiquidity3.timestamp, Seq(addInvalidLiquidity3), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsAndVSwapRemoveLiquidity: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, _, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap(10000, 1, 10000, 10000, 1, + 10000, 10000, 1000,10, 2000, 2000) + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts) + + removeLiquidity <- removeLiquidityVSwapGen(master, regVSwap.contractId, 100L, 100L, 100L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + removeInvalidLiquidity <- removeLiquidityVSwapGen(master, regVSwap.contractId, 2000L, 100L, 100L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + removeInvalidLiquidity2 <- removeLiquidityVSwapGen(master, regVSwap.contractId, 100L, 200L, 100L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + removeInvalidLiquidity3 <- removeLiquidityVSwapGen(master, regVSwap.contractId, 100L, 100L, 100L, ts - 1000000000000L, attach, fee + 10000000000L, ts) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, removeLiquidity, removeInvalidLiquidity, removeInvalidLiquidity2, removeInvalidLiquidity3) + + property("unable to remove liquidity") { + forAll(preconditionsAndVSwapRemoveLiquidity) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, + removeLiquidity: ExecuteContractFunctionTransaction, removeInvalidLiquidity: ExecuteContractFunctionTransaction, removeInvalidLiquidity2: ExecuteContractFunctionTransaction, removeInvalidLiquidity3: ExecuteContractFunctionTransaction) => + + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(removeLiquidity.timestamp, Seq(removeLiquidity), TransactionStatus.Success)) { (blockDiff) => + blockDiff.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // remove liquidity more than in pool + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(removeInvalidLiquidity.timestamp, Seq(removeInvalidLiquidity), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // remove liquidity with wrong amountAMin, remove liquidity with wrong amountBMin has been local tested successfully + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(removeInvalidLiquidity2.timestamp, Seq(removeInvalidLiquidity2), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // remove liquidity with wrong removeLiquidityDeadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(removeInvalidLiquidity3.timestamp, Seq(removeInvalidLiquidity3), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsAndVSwapSwapTokenForExactBaseToken: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, _, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap(10000, 1, 10000, 10000, 1, 10000, + 10000, 1000,10, 2000, 2000) + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts) + + swapTokenForExactBaseToken <- swapTokenForExactBaseTokenVSwapGen(master, regVSwap.contractId, 100L, 112L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + swapInvalidTokenForExactBaseToken <- swapTokenForExactBaseTokenVSwapGen(master, regVSwap.contractId, 100L, 111L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + swapInvalidTokenForExactBaseToken2 <- swapTokenForExactBaseTokenVSwapGen(master, regVSwap.contractId, 100L, 112L, ts - 1000000000000L, attach, fee + 10000000000L, ts) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, swapTokenForExactBaseToken, swapInvalidTokenForExactBaseToken, swapInvalidTokenForExactBaseToken2) + + property("unable to swap tokens for exact base token") { + forAll(preconditionsAndVSwapSwapTokenForExactBaseToken) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, swapTokenForExactBaseToken: ExecuteContractFunctionTransaction, swapInvalidTokenForExactBaseToken: ExecuteContractFunctionTransaction, swapInvalidTokenForExactBaseToken2: ExecuteContractFunctionTransaction) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapTokenForExactBaseToken), TransactionStatus.Success)) { (blockDiff) => + blockDiff.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // swap tokens for exact base token with wrong total supply + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(swapInvalidTokenForExactBaseToken.timestamp, Seq(swapInvalidTokenForExactBaseToken), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + // swap tokens for exact base token with wrong swapDeadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(swapInvalidTokenForExactBaseToken2.timestamp, Seq(swapInvalidTokenForExactBaseToken2), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + } + + val preconditionsAndVSwapSwapExactTokenForBaseToken: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, _, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap(10000, 1, 10000, 10000, 1, 10000, + 10000, 1000,10, 2000, 2000) + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts) + + swapExactTokenForBaseToken <- swapExactTokenForBaseTokenVSwapGen(master, regVSwap.contractId, 496, 990L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + swapInvalidExactTokenForBaseToken <- swapExactTokenForBaseTokenVSwapGen(master, regVSwap.contractId, 497, 990L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + swapInvalidExactTokenForBaseToken2 <- swapExactTokenForBaseTokenVSwapGen(master, regVSwap.contractId, 496, 990L, ts - 1000000000000L, attach, fee + 10000000000L, ts) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, swapExactTokenForBaseToken, swapInvalidExactTokenForBaseToken, swapInvalidExactTokenForBaseToken2) + + property("unable to swap exact token for base token") { + forAll(preconditionsAndVSwapSwapExactTokenForBaseToken) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, swapExactTokenForBaseToken: ExecuteContractFunctionTransaction, + swapInvalidExactTokenForBaseToken: ExecuteContractFunctionTransaction, swapInvalidExactTokenForBaseToken2: ExecuteContractFunctionTransaction) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapExactTokenForBaseToken), TransactionStatus.Success)) { (blockDiff) => + blockDiff.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // swap exact token for base token with wrong total supply + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(swapInvalidExactTokenForBaseToken.timestamp, Seq(swapInvalidExactTokenForBaseToken), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // swap exact token for base token with wrong deadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(swapInvalidExactTokenForBaseToken2.timestamp, Seq(swapInvalidExactTokenForBaseToken2), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsAndVSwapSwapTokenForExactTargetToken: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, _, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap(10000, 1, 10000, 10000, 1, 10000, + 10000, 1000,10, 2000, 2000) + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts) + + swapTokenForExactTargetToken <- swapTokenForExactTargetTokenVSwapGen(master, regVSwap.contractId, 100L, 112L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + swapInvalidTokenForExactTargetToken <- swapTokenForExactTargetTokenVSwapGen(master, regVSwap.contractId, 100L, 111L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + swapInvalidTokenForExactTargetToken2 <- swapTokenForExactTargetTokenVSwapGen(master, regVSwap.contractId, 100L, 112L, ts - 1000000000000L, attach, fee + 10000000000L, ts) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, swapTokenForExactTargetToken, swapInvalidTokenForExactTargetToken, swapInvalidTokenForExactTargetToken2) + + property("unable to swap token for exact target token") { + forAll(preconditionsAndVSwapSwapTokenForExactTargetToken) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, swapTokenForExactTargetToken: ExecuteContractFunctionTransaction, + swapInvalidTokenForExactTargetToken: ExecuteContractFunctionTransaction, swapInvalidTokenForExactTargetToken2: ExecuteContractFunctionTransaction) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapTokenForExactTargetToken), TransactionStatus.Success)) { (blockDiff) => + blockDiff.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // swap token for exact target token with wrong total supply + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(swapInvalidTokenForExactTargetToken.timestamp, Seq(swapInvalidTokenForExactTargetToken), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // swap token for exact target token with wrong deadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(swapInvalidTokenForExactTargetToken2.timestamp, Seq(swapInvalidTokenForExactTargetToken2), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsAndVSwapSwapExactTokenForTargetToken: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap(10000, 1, 10000, 10000, 1, 10000, + 10000, 1000,10, 2000, 2000) + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts) + + swapExactTokenForTargetToken <- swapExactTokenForTargetTokenVSwapGen(master, regVSwap.contractId, 90L, 100L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + swapInvalidExactTokenForTargetToken <- swapExactTokenForTargetTokenVSwapGen(master, regVSwap.contractId, 91L, 100L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + + swapInvalidExactTokenForTargetToken2 <- swapExactTokenForTargetTokenVSwapGen(master, regVSwap.contractId, 90L, 100L, ts - 1000000000000L, attach, fee + 10000000000L, ts) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, swapExactTokenForTargetToken, swapInvalidExactTokenForTargetToken, swapInvalidExactTokenForTargetToken2) + + property("unable to swap exact token for target token") { + forAll(preconditionsAndVSwapSwapExactTokenForTargetToken) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, swapExactTokenForTargetToken: ExecuteContractFunctionTransaction, + swapInvalidExactTokenForTargetToken: ExecuteContractFunctionTransaction, swapInvalidExactTokenForTargetToken2: ExecuteContractFunctionTransaction) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapExactTokenForTargetToken), TransactionStatus.Success)) { (blockDiff) => + blockDiff.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // swap exact token for target token with wrong total supply + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(swapInvalidExactTokenForTargetToken.timestamp, Seq(swapInvalidExactTokenForTargetToken), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // swap exact token for target token with wrong deadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(setSwap.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(swapInvalidExactTokenForTargetToken2.timestamp, Seq(swapInvalidExactTokenForTargetToken2), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } +} \ No newline at end of file From aabc1873088388ff02a50255ae89a665a966f667 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Wed, 23 Dec 2020 11:29:11 +0800 Subject: [PATCH 154/391] Add Invalid case in which the initial liquidity is less than minimum --- .../vswap/ExecuteVSwapInvalidDiffTest.scala | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala index a23793845..516e28cda 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala @@ -50,27 +50,27 @@ class ExecuteVSwapInvalidDiffTest extends PropSpec val preconditionsAndVSwapSetSwap: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, - ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { (genesis, genesis2, master, _, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- createABLiquidityTokenAndInitVSwap(1000, 1, 1000, 1000, 1, 1000, 1000, 1000,9, 100, 100) setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 10L, 10L, attach, fee + 10000000000L, ts) setInvalidSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 10L, attach, fee + 10000000000L, ts) + setInvalidSwap2 <- setSwapVSwapGen(master, regVSwap.contractId, 8L, 10L, attach, fee + 10000000000L, ts) } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, - depositB, depositLiquidity, setSwap, setInvalidSwap) + depositB, depositLiquidity, setSwap, setInvalidSwap, setInvalidSwap2) - // set swap token A more than deposit, set swap token B more than deposit has been local tested successfully property("set swap more than deposit") { forAll(preconditionsAndVSwapSetSwap) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, - depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, setInvalidSwap: ExecuteContractFunctionTransaction) => + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, setInvalidSwap: ExecuteContractFunctionTransaction, setInvalidSwap2: ExecuteContractFunctionTransaction) => assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositLiquidity.timestamp, Seq(regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), TestBlock.createWithTxStatus(setSwap.timestamp, Seq(setSwap), TransactionStatus.Success)) { (blockDiff) => blockDiff.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } - + // set swap token A more than deposit, set swap token B more than deposit has been local tested successfully assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositLiquidity.timestamp, Seq(regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), TestBlock.createWithTxStatus(setInvalidSwap.timestamp, Seq(setInvalidSwap), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => @@ -78,6 +78,14 @@ class ExecuteVSwapInvalidDiffTest extends PropSpec blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } + // set swap less than minimum liquidity (amountADesired), set swap less than minimum liquidity (amountBDesired) has been local tested successfully + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositLiquidity.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), + TestBlock.createWithTxStatus(setInvalidSwap2.timestamp, Seq(setInvalidSwap2), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } } } From 51fcf766c2d6d96ff34d159af31940e53ccb3e3c Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 24 Dec 2020 16:05:00 +0800 Subject: [PATCH 155/391] add supersede --- .../blockchain/contract/ContractVStableSwap.scala | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index ce5f9ef29..0e59fafbd 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -7,7 +7,7 @@ import vsys.utils.serialization.Deser object ContractVStableSwap { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), - Seq(), // Triggers + Seq(initTrigger, depositTrigger, withdrawTrigger), // Triggers Seq(), // Functions stateVarSeq, // StateVars stateMapSeq, // StateMaps @@ -123,6 +123,17 @@ object ContractVStableSwap { val withdrawTextualBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) // Functions + // Supersede + val supersedeId: Short = 0 + val supersedePara: Seq[String] = Seq("newOwner", + "maker") + val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val supersedeOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(makerStateVar.index, 1.toByte), + assertSigner ++ Array(1.toByte), + cdbvSet ++ Array(makerStateVar.index, 0.toByte)) + lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) + val supersedeTextualBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) // Textual From dcb577f7776dc4007992534ad89b014924854eb4 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 24 Dec 2020 16:16:02 +0800 Subject: [PATCH 156/391] add contract last token API and remove contract data api key request --- .../api/http/contract/ContractApiRoute.scala | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 9ff9a14b1..420147c63 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -70,6 +70,21 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx ))).getOrElse(InvalidContractAddress) } + @Path("/lastTokenIndex/{contractId}") + @ApiOperation(value = "Last Token Index", notes = "Token contract last token index", httpMethod = "Get") + @ApiImplicitParams(Array( + new ApiImplicitParam(name = "contractId", value = "Contract ID", required = true, dataType = "string", paramType = "path") + )) + def lastToken: Route = (get & path("lastTokenIndex" / Segment)) { contractId => + ByteStr.decodeBase58(contractId) match { + case Success(id) => complete(Json.obj( + "contractId" -> contractId, + "lastTokenIndex" -> state.contractTokens(id) + )) + case _ => complete(InvalidAddress) + } + } + @Path("/content/{contractId}") @ApiOperation(value = "Contract content", notes = "Get contract content associated with a contract id.", httpMethod = "GET") @ApiImplicitParams(Array( @@ -86,13 +101,13 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx } } - @Path("data/{contractId}/{key}") + @Path("/data/{contractId}/{key}") @ApiOperation(value = "Contract Data", notes = "Contract data by given contract ID and key (default numerical 0).", httpMethod = "Get", authorizations = Array(new Authorization("api_key"))) @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract Account", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "key", value = "Key", required = true, dataType = "string", paramType = "path") )) - def getContractData: Route = (get & withAuth & path("data" / Segment / Segment)) { (contractId, key) => + def getContractData: Route = (get & path("data" / Segment / Segment)) { (contractId, key) => complete(dataJson(contractId, key)) } @@ -178,7 +193,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx } } - @Path("balance/{address}/{tokenId}") + @Path("/balance/{address}/{tokenId}") @ApiOperation(value = "Token's balance", notes = "Account's balance by given token", httpMethod = "Get") @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path"), @@ -253,7 +268,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) def execute: Route = processRequest("execute", (t: ExecuteContractFunctionRequest) => doBroadcast(TransactionFactory.executeContractFunction(t, wallet, time))) - @Path("contractId/{contractId}/tokenIndex/{tokenIndex}") + @Path("/contractId/{contractId}/tokenIndex/{tokenIndex}") @ApiOperation(value = "Token's Id", notes = "Token Id from contract Id and token index", httpMethod = "Get") @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract ID", required = true, dataType = "string", paramType = "path"), From 0c53b5777d942778e162643990d2f60ecee6e6d9 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Mon, 28 Dec 2020 16:26:04 +0800 Subject: [PATCH 157/391] assert contract db values --- .../vswap/ExecuteVSwapValidDiffTest.scala | 82 ++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala index 3379e5a0f..1c6d54dd9 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala @@ -3,12 +3,16 @@ package vsys.blockchain.state.contract.vswap import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} import vsys.blockchain.contract.vswap.{VSwapContractGen, VSwapFunctionHelperGen} import vsys.blockchain.state.diffs._ import vsys.blockchain.transaction.contract._ +import vsys.blockchain.state._ import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import com.google.common.primitives.{Bytes, Ints} class ExecuteVSwapValidDiffTest extends PropSpec with PropertyChecks @@ -56,8 +60,34 @@ class ExecuteVSwapValidDiffTest extends PropSpec withdrawLiquidity: ExecuteContractFunctionTransaction) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), - TestBlock.createWithTxStatus(withdrawLiquidity.timestamp, Seq(withdrawLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => + TestBlock.createWithTxStatus(withdrawLiquidity.timestamp, Seq(withdrawA, withdrawB, withdrawLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = withdrawLiquidity.proofs.firstCurveProof.explicitGet().publicKey + val vswapContractId = regVSwap.contractId.bytes + + val tokenAContractId = regTokenA.contractId.bytes + val tokenBContractId = regTokenB.contractId.bytes + val liquidityContractId = regLiquidity.contractId.bytes + + val tokenAId = tokenIdFromBytes(tokenAContractId.arr, Ints.toByteArray(0)).explicitGet() + val tokenBId = tokenIdFromBytes(tokenBContractId.arr, Ints.toByteArray(0)).explicitGet() + val liquidityTokenId = tokenIdFromBytes(liquidityContractId.arr, Ints.toByteArray(0)).explicitGet() + + val contractTokenAIdBalanceKey = ByteStr(Bytes.concat(tokenAId.arr, vswapContractId.arr)) + val masterTokenAIdBalanceKey = ByteStr(Bytes.concat(tokenAId.arr, master.toAddress.bytes.arr)) + newState.tokenAccountBalance(masterTokenAIdBalanceKey) shouldBe 1000L + newState.tokenAccountBalance(contractTokenAIdBalanceKey) shouldBe 0L + + val contractTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, vswapContractId.arr)) + val masterTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, master.toAddress.bytes.arr)) + newState.tokenAccountBalance(masterTokenBBalanceKey) shouldBe 1000L + newState.tokenAccountBalance(contractTokenBBalanceKey) shouldBe 0L + + val contractLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, vswapContractId.arr)) + val masterLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, master.toAddress.bytes.arr)) + newState.tokenAccountBalance(masterLiquidityBalanceKey) shouldBe 10L + newState.tokenAccountBalance(contractLiquidityBalanceKey) shouldBe 990L } } } @@ -93,6 +123,17 @@ class ExecuteVSwapValidDiffTest extends PropSpec regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity))), TestBlock.createWithTxStatus(setSwap.timestamp, Seq(setSwap), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = setSwap.proofs.firstCurveProof.explicitGet().publicKey + val vswapContractId = regVSwap.contractId.bytes + val tokenABalanceKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(0.toByte), DataEntry(master.toAddress.bytes.arr, DataType.Address).bytes)) //tokenAReservedStateVar + newState.contractNumInfo(tokenABalanceKey) shouldEqual 90L + val tokenBBalanceKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(1.toByte), DataEntry(master.toAddress.bytes.arr, DataType.Address).bytes)) //tokenAReservedStateVar + newState.contractNumInfo(tokenBBalanceKey) shouldEqual 90L + val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenAReservedKey) shouldEqual 10L + val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenBReservedKey) shouldEqual 10L } } } @@ -132,6 +173,12 @@ class ExecuteVSwapValidDiffTest extends PropSpec regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), TestBlock.createWithTxStatus(setSwap.timestamp, Seq(addLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val vswapContractId = regVSwap.contractId.bytes + val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenAReservedKey) shouldEqual 2000L + val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenBReservedKey) shouldEqual 2000L } } } @@ -175,6 +222,15 @@ class ExecuteVSwapValidDiffTest extends PropSpec regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap, addLiquidity))), TestBlock.createWithTxStatus(setSwap.timestamp, Seq(removeLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val vswapContractId = regVSwap.contractId.bytes + val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenAReservedKey) shouldEqual 1000L + val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenBReservedKey) shouldEqual 1000L + + val tokenLiquidityLeftKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(9.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenLiquidityLeftKey) shouldEqual 9000L } } } @@ -214,6 +270,12 @@ class ExecuteVSwapValidDiffTest extends PropSpec regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapTokenForExactBaseToken), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val vswapContractId = regVSwap.contractId.bytes + val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenAReservedKey) shouldEqual 900L + val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenBReservedKey) shouldEqual 1112L } } } @@ -254,6 +316,12 @@ class ExecuteVSwapValidDiffTest extends PropSpec regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapExactTokenForBaseToken), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val vswapContractId = regVSwap.contractId.bytes + val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenAReservedKey) shouldEqual 910L + val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenBReservedKey) shouldEqual 1100L } } } @@ -294,6 +362,12 @@ class ExecuteVSwapValidDiffTest extends PropSpec regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapTokenForExactTargetToken), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val vswapContractId = regVSwap.contractId.bytes + val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenAReservedKey) shouldEqual 1112L + val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenBReservedKey) shouldEqual 900L } } } @@ -334,6 +408,12 @@ class ExecuteVSwapValidDiffTest extends PropSpec regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapExactTokenForTargetToken), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val vswapContractId = regVSwap.contractId.bytes + val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenAReservedKey) shouldEqual 1100L + val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar + newState.contractNumInfo(tokenBReservedKey) shouldEqual 910L } } } From b77ef532f209e8fd26f72f56d7ed1fbbbe6113da Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 28 Dec 2020 18:47:08 +0800 Subject: [PATCH 158/391] add last token func to path prefix --- src/main/scala/vsys/api/http/contract/ContractApiRoute.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 420147c63..82adb90ab 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -31,7 +31,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx extends ApiRoute with BroadcastRoute { override val route = pathPrefix("contract") { - register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData + register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData ~ lastToken } @Path("/register") From 0e4f907f501382902f0f2573a487851363d13530 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 31 Dec 2020 09:25:45 +0800 Subject: [PATCH 159/391] change default chain type to MAINNET --- src/main/resources/application.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index bc7d34918..a457c4ef5 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -111,7 +111,7 @@ vsys { minimum-in-memory-diff-blocks = 3600 # Blockchain type. Could be TESTNET | MAINNET | CUSTOM. Default value is TESTNET. - type = TESTNET + type = MAINNET # 'custom' section present only if CUSTOM blockchain type is set. It's impossible to overwrite predefined 'testnet' and 'mainnet' configurations. # custom { From a07caf927caed6957960107e258d5e4c573f6dae Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 31 Dec 2020 10:25:11 +0800 Subject: [PATCH 160/391] change default port to 9921 --- src/main/resources/application.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index a457c4ef5..fb83d551f 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -28,13 +28,13 @@ vsys { # In some cases, you may both set `decalred-address` and enable UPnP (e.g. when IGD can't reliably determine its # external IP address). In such cases the node will attempt to configure an IGD to pass traffic from external port # to `bind-address:port`. Please note, however, that this setup is not recommended. - # declared-address = "1.2.3.4:9923" + # declared-address = "1.2.3.4:9921" # Network address bind-address = "0.0.0.0" # Port number - port = 9923 + port = 9921 # Node name to send during handshake. Comment this string out to set random node name. # node-name = "default-node-name" @@ -110,7 +110,7 @@ vsys { # Min buffer size. Fast rollback is possible up to this value. minimum-in-memory-diff-blocks = 3600 - # Blockchain type. Could be TESTNET | MAINNET | CUSTOM. Default value is TESTNET. + # Blockchain type. Could be TESTNET | MAINNET | CUSTOM. Default value is MAINNET. type = MAINNET # 'custom' section present only if CUSTOM blockchain type is set. It's impossible to overwrite predefined 'testnet' and 'mainnet' configurations. From 654a28394c4be5616a05fd04eb4632503b6b442b Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 31 Dec 2020 11:00:44 +0800 Subject: [PATCH 161/391] add known peer addresses --- src/main/resources/application.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index fb83d551f..2743a4cdb 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -43,7 +43,7 @@ vsys { # nonce = 0 # List of IP addresses of well known nodes. - known-peers = [] + known-peers = ["gemmer.vcoin.systems:9921","vnode.vcoin.systems:9921","gemmer.vos.systems:9921","vnode.vos.systems:9921"] # How long the information about peer stays in database after the last communication with it peers-data-residence-time = 1d From 3d6fadc359b0d91eb8a6e526ca8160ab5ec253f3 Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 6 Jan 2021 11:57:13 +0800 Subject: [PATCH 162/391] update state var --- .../contract/ContractVStableSwap.scala | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 0e59fafbd..6468fdd6f 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -15,22 +15,15 @@ object ContractVStableSwap { ).explicitGet() // State Var - val stateVarName = List("maker", "baseTokenId", "targetTokenId", "swapStatus", "minSwapAmount", "maxSwapAmount", - "lastUpdateTime", "updateGap", "feeBase", "feeTarget") + val stateVarName = List("maker", "baseTokenId", "targetTokenId", "maxOrderPerUser", "unitPriceBase", "unitPriceTarget") val makerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) val baseTokenIdStateVar: StateVar = StateVar(1.toByte, DataType.TokenId.id.toByte) val targetTokenIdStateVar: StateVar = StateVar(2.toByte, DataType.TokenId.id.toByte) - val swapStatusStateVar: StateVar = StateVar(3.toByte, DataType.Boolean.id.toByte) - val minSwapAmountStateVar: StateVar = StateVar(4.toByte, DataType.Amount.id.toByte) - val maxSwapAmountStateVar: StateVar = StateVar(5.toByte, DataType.Amount.id.toByte) - val lastUpdateTimeStateVar: StateVar = StateVar(6.toByte, DataType.Timestamp.id.toByte) - val updateGapStateVar: StateVar = StateVar(7.toByte, DataType.Timestamp.id.toByte) - val feeBaseStateVar: StateVar = StateVar(8.toByte, DataType.Amount.id.toByte) - val feeTargetStateVar: StateVar = StateVar(9.toByte, DataType.Amount.id.toByte) - lazy val stateVarSeq = Seq(makerStateVar.arr, baseTokenIdStateVar.arr, targetTokenIdStateVar.arr, swapStatusStateVar.arr, - minSwapAmountStateVar.arr, maxSwapAmountStateVar.arr, - lastUpdateTimeStateVar.arr, updateGapStateVar.arr, - feeBaseStateVar.arr, feeTargetStateVar.arr) + val maxOrderPerUserStateVar: StateVar = StateVar(3.toByte, DataType.Amount.id.toByte) + val unitPriceBaseStateVar: StateVar = StateVar(4.toByte, DataType.Amount.id.toByte) + val unitPriceTargetStateVar: StateVar = StateVar(5.toByte, DataType.Amount.id.toByte) + lazy val stateVarSeq = Seq(makerStateVar.arr, baseTokenIdStateVar.arr, targetTokenIdStateVar.arr, maxOrderPerUserStateVar.arr, + unitPriceBaseStateVar.arr, unitPriceTargetStateVar.arr) lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map From 379208045046a850457488ae9687ad7f1c116c86 Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 6 Jan 2021 12:01:03 +0800 Subject: [PATCH 163/391] update init trigger --- .../contract/ContractVStableSwap.scala | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 6468fdd6f..d2dc6414b 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -37,16 +37,18 @@ object ContractVStableSwap { // Initialization Trigger val initId: Short = 0 - val initPara: Seq[String] = Seq("baseTokenId", "targetTokenId") ++ - Seq("signer", "swapStatus") - val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.TokenId.id.toByte) + val initPara: Seq[String] = Seq("baseTokenId", "targetTokenId", "maxOrderPerUser", "unitPriceBase", "unitPriceTarget") ++ + Seq("signer") + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.Amount.id.toByte, + DataType.Amount.id.toByte, DataType.Amount.id.toByte) val initTriggerOpcs: Seq[Array[Byte]] = Seq( - loadSigner ++ Array(2.toByte), - cdbvSet ++ Array(makerStateVar.index, 2.toByte), + loadSigner ++ Array(5.toByte), + cdbvSet ++ Array(makerStateVar.index, 5.toByte), cdbvSet ++ Array(baseTokenIdStateVar.index, 0.toByte), cdbvSet ++ Array(targetTokenIdStateVar.index, 1.toByte), - basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), - cdbvSet ++ Array(swapStatusStateVar.index, 5.toByte) + cdbvSet ++ Array(maxOrderPerUserStateVar.index, 2.toByte), + cdbvSet ++ Array(unitPriceBaseStateVar.index, 3.toByte), + cdbvSet ++ Array(unitPriceTargetStateVar.index, 4.toByte) ) lazy val initTrigger: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initTriggerOpcs) val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) From 38d1b08abc64f5abb44debd20a4541b9879911de Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 6 Jan 2021 12:15:37 +0800 Subject: [PATCH 164/391] update state map --- .../contract/ContractVStableSwap.scala | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index d2dc6414b..e40639f55 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -29,11 +29,33 @@ object ContractVStableSwap { // State Map val stateMapBaseTokenBalance = List("baseTokenBalance", "userAddress", "balance") val stateMapTargetTokenBalance = List("targetTokenBalance", "userAddress", "balance") + val stateMapUserOrders = List("userOrders", "userAddress", "orderNum") + val stateMapFeeBase = List("feeBase", "orderId", "fee") + val stateMapFeeTarget = List("feeTarget", "orderId", "fee") + val stateMapMinBase = List("minBase", "orderId", "amount") + val stateMapMaxBase = List("maxBase", "orderId", "amount") + val stateMapMinTarget = List("minTarget", "orderId", "amount") + val stateMapMaxTarget = List("maxTarget", "orderId", "amount") + val stateMapPriceBase = List("priceBase", "orderId", "price") + val stateMapPriceTarget = List("priceTarget", "orderId", "price") val baseTokenBalanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) val targetTokenBalanceMap: StateMap = StateMap(1.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val userOrdersMap: StateMap = StateMap(2.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val feeBaseMap: StateMap = StateMap(3.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val feeTargetMap: StateMap = StateMap(4.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val minBaseMap: StateMap = StateMap(5.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val maxBaseMap: StateMap = StateMap(6.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val minTargetMap: StateMap = StateMap(7.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val maxTargetMap: StateMap = StateMap(8.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val priceBaseMap: StateMap = StateMap(9.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val priceTargetMap: StateMap = StateMap(10.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) - lazy val stateMapSeq = Seq(baseTokenBalanceMap.arr, targetTokenBalanceMap.arr) - lazy val stateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapBaseTokenBalance, stateMapTargetTokenBalance)) + lazy val stateMapSeq = Seq(baseTokenBalanceMap.arr, targetTokenBalanceMap.arr, userOrdersMap.arr, + feeBaseMap.arr, feeTargetMap.arr, minBaseMap.arr, maxBaseMap.arr, + minTargetMap.arr, maxTargetMap.arr, priceBaseMap.arr, priceTargetMap.arr) + lazy val stateMapTextual: Array[Byte] = textualStateMap( + Seq(stateMapBaseTokenBalance, stateMapTargetTokenBalance, stateMapUserOrders, stateMapFeeBase, stateMapFeeTarget, + stateMapMinBase, stateMapMaxBase, stateMapMinTarget, stateMapMaxTarget, stateMapPriceBase, stateMapPriceTarget)) // Initialization Trigger val initId: Short = 0 From 6eca84695b1fa7b39e3a48eafc614ee4034c45bb Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Wed, 6 Jan 2021 14:32:11 +0800 Subject: [PATCH 165/391] add functions for db keys and fill in missing db value tests --- .../vswap/ExecuteVSwapValidDiffTest.scala | 203 ++++++++++++++---- 1 file changed, 156 insertions(+), 47 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala index 1c6d54dd9..fc118e63d 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala @@ -12,7 +12,8 @@ import vsys.blockchain.state.diffs._ import vsys.blockchain.transaction.contract._ import vsys.blockchain.state._ import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} -import com.google.common.primitives.{Bytes, Ints} +import com.google.common.primitives.{Bytes, Ints, Longs} +import vsys.account.PublicKeyAccount class ExecuteVSwapValidDiffTest extends PropSpec with PropertyChecks @@ -26,6 +27,49 @@ class ExecuteVSwapValidDiffTest extends PropSpec private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + def getContractTokenBalanceKeys(tokenAContractId: Array[Byte], tokenBContractId: Array[Byte], liquidityContractId: Array[Byte], vSwapContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr) = { + val tokenAId = tokenIdFromBytes(tokenAContractId, Ints.toByteArray(0)).explicitGet() + val tokenBId = tokenIdFromBytes(tokenBContractId, Ints.toByteArray(0)).explicitGet() + val liquidityTokenId = tokenIdFromBytes(liquidityContractId, Ints.toByteArray(0)).explicitGet() + + val contractTokenABalanceKey = ByteStr(Bytes.concat(tokenAId.arr, vSwapContractId)) + val contractTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, vSwapContractId)) + val contractLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, vSwapContractId)) + + (contractTokenABalanceKey, contractTokenBBalanceKey, contractLiquidityBalanceKey) + } + + def getUserTokenBalanceKeys(tokenAContractId: Array[Byte], tokenBContractId: Array[Byte], liquidityContractId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr) = { + val tokenAId = tokenIdFromBytes(tokenAContractId, Ints.toByteArray(0)).explicitGet() + val tokenBId = tokenIdFromBytes(tokenBContractId, Ints.toByteArray(0)).explicitGet() + val liquidityTokenId = tokenIdFromBytes(liquidityContractId, Ints.toByteArray(0)).explicitGet() + + val masterTokenABalanceKey = ByteStr(Bytes.concat(tokenAId.arr, user.toAddress.bytes.arr)) + val masterTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, user.toAddress.bytes.arr)) + val masterLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, user.toAddress.bytes.arr)) + + (masterTokenABalanceKey, masterTokenBBalanceKey, masterLiquidityBalanceKey) + } + + def getSwapContractStateVarKeys(vSwapContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr) = { + val swapStatusKey = ByteStr(Bytes.concat(vSwapContractId, Array(4.toByte))) + val minimumLiquidityKey = ByteStr(Bytes.concat(vSwapContractId, Array(5.toByte))) + val tokenAReservedKey = ByteStr(Bytes.concat(vSwapContractId, Array(6.toByte))) + val tokenBReservedKey = ByteStr(Bytes.concat(vSwapContractId, Array(7.toByte))) + val totalSupplyKey = ByteStr(Bytes.concat(vSwapContractId, Array(8.toByte))) + val liquidityTokenLeft = ByteStr(Bytes.concat(vSwapContractId, Array(9.toByte))) + + (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) + } + + def getSwapContractStateMapKeys(vSwapContractId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr) = { + val stateMapTokenABalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(0.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val stateMapTokenBBalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(1.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val stateMapLiquidityTokenBalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(2.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + + (stateMapTokenABalanceKey, stateMapTokenBBalanceKey, stateMapLiquidityTokenBalanceKey) + } + val preconditionsAndVSwapDepositAndWithdrawLiquidityTokens: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, @@ -43,8 +87,8 @@ class ExecuteVSwapValidDiffTest extends PropSpec 1000, // total supply of liquidity token 1000, // unity of liquidity token 10, // minimum liquidity - 10, // deposit amount of token A - 10) // deposit amount of token B + 1000, // deposit amount of token A + 1000) // deposit amount of token B //withdraw tokens withdrawTokenA <- withdrawToken(master, regTokenA.contractId, regVSwap.contractId.bytes.arr, master.toAddress.bytes.arr, 10L, fee, ts + 10) withdrawTokenB <- withdrawToken(master, regTokenB.contractId, regVSwap.contractId.bytes.arr, master.toAddress.bytes.arr, 10L, fee, ts + 11) @@ -64,28 +108,21 @@ class ExecuteVSwapValidDiffTest extends PropSpec blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success val master = withdrawLiquidity.proofs.firstCurveProof.explicitGet().publicKey - val vswapContractId = regVSwap.contractId.bytes + val vSwapContractId = regVSwap.contractId.bytes.arr - val tokenAContractId = regTokenA.contractId.bytes - val tokenBContractId = regTokenB.contractId.bytes - val liquidityContractId = regLiquidity.contractId.bytes + val tokenAContractId = regTokenA.contractId.bytes.arr + val tokenBContractId = regTokenB.contractId.bytes.arr + val liquidityContractId = regLiquidity.contractId.bytes.arr - val tokenAId = tokenIdFromBytes(tokenAContractId.arr, Ints.toByteArray(0)).explicitGet() - val tokenBId = tokenIdFromBytes(tokenBContractId.arr, Ints.toByteArray(0)).explicitGet() - val liquidityTokenId = tokenIdFromBytes(liquidityContractId.arr, Ints.toByteArray(0)).explicitGet() + val (contractTokenABalanceKey, contractTokenBBalanceKey, contractLiquidityBalanceKey) = getContractTokenBalanceKeys(tokenAContractId, tokenBContractId, liquidityContractId, vSwapContractId) + val (masterTokenABalanceKey, masterTokenBBalanceKey, masterLiquidityBalanceKey) = getUserTokenBalanceKeys(tokenAContractId, tokenBContractId, liquidityContractId, master) - val contractTokenAIdBalanceKey = ByteStr(Bytes.concat(tokenAId.arr, vswapContractId.arr)) - val masterTokenAIdBalanceKey = ByteStr(Bytes.concat(tokenAId.arr, master.toAddress.bytes.arr)) - newState.tokenAccountBalance(masterTokenAIdBalanceKey) shouldBe 1000L - newState.tokenAccountBalance(contractTokenAIdBalanceKey) shouldBe 0L + newState.tokenAccountBalance(masterTokenABalanceKey) shouldBe 10L + newState.tokenAccountBalance(contractTokenABalanceKey) shouldBe 990L - val contractTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, vswapContractId.arr)) - val masterTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, master.toAddress.bytes.arr)) - newState.tokenAccountBalance(masterTokenBBalanceKey) shouldBe 1000L - newState.tokenAccountBalance(contractTokenBBalanceKey) shouldBe 0L + newState.tokenAccountBalance(masterTokenBBalanceKey) shouldBe 10L + newState.tokenAccountBalance(contractTokenBBalanceKey) shouldBe 990L - val contractLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, vswapContractId.arr)) - val masterLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, master.toAddress.bytes.arr)) newState.tokenAccountBalance(masterLiquidityBalanceKey) shouldBe 10L newState.tokenAccountBalance(contractLiquidityBalanceKey) shouldBe 990L } @@ -125,15 +162,24 @@ class ExecuteVSwapValidDiffTest extends PropSpec blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success val master = setSwap.proofs.firstCurveProof.explicitGet().publicKey - val vswapContractId = regVSwap.contractId.bytes - val tokenABalanceKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(0.toByte), DataEntry(master.toAddress.bytes.arr, DataType.Address).bytes)) //tokenAReservedStateVar - newState.contractNumInfo(tokenABalanceKey) shouldEqual 90L - val tokenBBalanceKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(1.toByte), DataEntry(master.toAddress.bytes.arr, DataType.Address).bytes)) //tokenAReservedStateVar - newState.contractNumInfo(tokenBBalanceKey) shouldEqual 90L - val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + val vSwapContractId = regVSwap.contractId.bytes.arr + + val (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) = getSwapContractStateVarKeys(vSwapContractId) + val (masterStateMapTokenABalanceKey, masterStateMapTokenBBalanceKey, masterStateMapLiquidityTokenBalanceKey) = getSwapContractStateMapKeys(vSwapContractId, master) + + newState.contractInfo(swapStatusKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(minimumLiquidityKey) shouldEqual Some(DataEntry(Longs.toByteArray(9), DataType.Amount)) newState.contractNumInfo(tokenAReservedKey) shouldEqual 10L - val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar newState.contractNumInfo(tokenBReservedKey) shouldEqual 10L + newState.contractNumInfo(totalSupplyKey) shouldEqual 10L // sqrt(10 * 10) + newState.contractNumInfo(liquidityTokenLeft) shouldEqual 990L // 1000 - sqrt(10*10) + + newState.contractNumInfo(masterStateMapTokenABalanceKey) shouldEqual 90L + newState.contractNumInfo(masterStateMapTokenBBalanceKey) shouldEqual 90L + newState.contractNumInfo(masterStateMapLiquidityTokenBalanceKey) shouldEqual 1L // sqrt(10 * 10) - 9 + + + } } } @@ -174,11 +220,22 @@ class ExecuteVSwapValidDiffTest extends PropSpec TestBlock.createWithTxStatus(setSwap.timestamp, Seq(addLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success - val vswapContractId = regVSwap.contractId.bytes - val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + val master = setSwap.proofs.firstCurveProof.explicitGet().publicKey + val vSwapContractId = regVSwap.contractId.bytes.arr + + val (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) = getSwapContractStateVarKeys(vSwapContractId) + val (masterStateMapTokenABalanceKey, masterStateMapTokenBBalanceKey, masterStateMapLiquidityTokenBalanceKey) = getSwapContractStateMapKeys(vSwapContractId, master) + + newState.contractInfo(swapStatusKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(minimumLiquidityKey) shouldEqual Some(DataEntry(Longs.toByteArray(10), DataType.Amount)) newState.contractNumInfo(tokenAReservedKey) shouldEqual 2000L - val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar newState.contractNumInfo(tokenBReservedKey) shouldEqual 2000L + newState.contractNumInfo(totalSupplyKey) shouldEqual 2000L + newState.contractNumInfo(liquidityTokenLeft) shouldEqual 8000L + + newState.contractNumInfo(masterStateMapTokenABalanceKey) shouldEqual 0L + newState.contractNumInfo(masterStateMapTokenBBalanceKey) shouldEqual 0L + newState.contractNumInfo(masterStateMapLiquidityTokenBalanceKey) shouldEqual 1990L } } } @@ -223,14 +280,22 @@ class ExecuteVSwapValidDiffTest extends PropSpec TestBlock.createWithTxStatus(setSwap.timestamp, Seq(removeLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success - val vswapContractId = regVSwap.contractId.bytes - val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + val master = setSwap.proofs.firstCurveProof.explicitGet().publicKey + val vSwapContractId = regVSwap.contractId.bytes.arr + + val (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) = getSwapContractStateVarKeys(vSwapContractId) + val (masterStateMapTokenABalanceKey, masterStateMapTokenBBalanceKey, masterStateMapLiquidityTokenBalanceKey) = getSwapContractStateMapKeys(vSwapContractId, master) + + newState.contractInfo(swapStatusKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(minimumLiquidityKey) shouldEqual Some(DataEntry(Longs.toByteArray(10), DataType.Amount)) newState.contractNumInfo(tokenAReservedKey) shouldEqual 1000L - val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar newState.contractNumInfo(tokenBReservedKey) shouldEqual 1000L + newState.contractNumInfo(totalSupplyKey) shouldEqual 1000L + newState.contractNumInfo(liquidityTokenLeft) shouldEqual 9000L - val tokenLiquidityLeftKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(9.toByte))) //tokenAReservedStateVar - newState.contractNumInfo(tokenLiquidityLeftKey) shouldEqual 9000L + newState.contractNumInfo(masterStateMapTokenABalanceKey) shouldEqual 1000L + newState.contractNumInfo(masterStateMapTokenBBalanceKey) shouldEqual 1000L + newState.contractNumInfo(masterStateMapLiquidityTokenBalanceKey) shouldEqual 990L } } } @@ -271,11 +336,22 @@ class ExecuteVSwapValidDiffTest extends PropSpec TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapTokenForExactBaseToken), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success - val vswapContractId = regVSwap.contractId.bytes - val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + val master = setSwap.proofs.firstCurveProof.explicitGet().publicKey + val vSwapContractId = regVSwap.contractId.bytes.arr + + val (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) = getSwapContractStateVarKeys(vSwapContractId) + val (masterStateMapTokenABalanceKey, masterStateMapTokenBBalanceKey, masterStateMapLiquidityTokenBalanceKey) = getSwapContractStateMapKeys(vSwapContractId, master) + + newState.contractInfo(swapStatusKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(minimumLiquidityKey) shouldEqual Some(DataEntry(Longs.toByteArray(10), DataType.Amount)) newState.contractNumInfo(tokenAReservedKey) shouldEqual 900L - val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar newState.contractNumInfo(tokenBReservedKey) shouldEqual 1112L + newState.contractNumInfo(totalSupplyKey) shouldEqual 1000L + newState.contractNumInfo(liquidityTokenLeft) shouldEqual 9000L + + newState.contractNumInfo(masterStateMapTokenABalanceKey) shouldEqual 1100L + newState.contractNumInfo(masterStateMapTokenBBalanceKey) shouldEqual 888L + newState.contractNumInfo(masterStateMapLiquidityTokenBalanceKey) shouldEqual 990L } } } @@ -317,11 +393,22 @@ class ExecuteVSwapValidDiffTest extends PropSpec TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapExactTokenForBaseToken), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success - val vswapContractId = regVSwap.contractId.bytes - val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + val master = setSwap.proofs.firstCurveProof.explicitGet().publicKey + val vSwapContractId = regVSwap.contractId.bytes.arr + + val (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) = getSwapContractStateVarKeys(vSwapContractId) + val (masterStateMapTokenABalanceKey, masterStateMapTokenBBalanceKey, masterStateMapLiquidityTokenBalanceKey) = getSwapContractStateMapKeys(vSwapContractId, master) + + newState.contractInfo(swapStatusKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(minimumLiquidityKey) shouldEqual Some(DataEntry(Longs.toByteArray(10), DataType.Amount)) newState.contractNumInfo(tokenAReservedKey) shouldEqual 910L - val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar newState.contractNumInfo(tokenBReservedKey) shouldEqual 1100L + newState.contractNumInfo(totalSupplyKey) shouldEqual 1000L + newState.contractNumInfo(liquidityTokenLeft) shouldEqual 9000L + + newState.contractNumInfo(masterStateMapTokenABalanceKey) shouldEqual 1090L + newState.contractNumInfo(masterStateMapTokenBBalanceKey) shouldEqual 900L + newState.contractNumInfo(masterStateMapLiquidityTokenBalanceKey) shouldEqual 990L } } } @@ -363,11 +450,22 @@ class ExecuteVSwapValidDiffTest extends PropSpec TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapTokenForExactTargetToken), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success - val vswapContractId = regVSwap.contractId.bytes - val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + val master = setSwap.proofs.firstCurveProof.explicitGet().publicKey + val vSwapContractId = regVSwap.contractId.bytes.arr + + val (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) = getSwapContractStateVarKeys(vSwapContractId) + val (masterStateMapTokenABalanceKey, masterStateMapTokenBBalanceKey, masterStateMapLiquidityTokenBalanceKey) = getSwapContractStateMapKeys(vSwapContractId, master) + + newState.contractInfo(swapStatusKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(minimumLiquidityKey) shouldEqual Some(DataEntry(Longs.toByteArray(10), DataType.Amount)) newState.contractNumInfo(tokenAReservedKey) shouldEqual 1112L - val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar newState.contractNumInfo(tokenBReservedKey) shouldEqual 900L + newState.contractNumInfo(totalSupplyKey) shouldEqual 1000L + newState.contractNumInfo(liquidityTokenLeft) shouldEqual 9000L + + newState.contractNumInfo(masterStateMapTokenABalanceKey) shouldEqual 888L + newState.contractNumInfo(masterStateMapTokenBBalanceKey) shouldEqual 1100L + newState.contractNumInfo(masterStateMapLiquidityTokenBalanceKey) shouldEqual 990L } } } @@ -409,11 +507,22 @@ class ExecuteVSwapValidDiffTest extends PropSpec TestBlock.createWithTxStatus(setSwap.timestamp, Seq(swapExactTokenForTargetToken), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success - val vswapContractId = regVSwap.contractId.bytes - val tokenAReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(6.toByte))) //tokenAReservedStateVar + val master = setSwap.proofs.firstCurveProof.explicitGet().publicKey + val vSwapContractId = regVSwap.contractId.bytes.arr + + val (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) = getSwapContractStateVarKeys(vSwapContractId) + val (masterStateMapTokenABalanceKey, masterStateMapTokenBBalanceKey, masterStateMapLiquidityTokenBalanceKey) = getSwapContractStateMapKeys(vSwapContractId, master) + + newState.contractInfo(swapStatusKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(minimumLiquidityKey) shouldEqual Some(DataEntry(Longs.toByteArray(10), DataType.Amount)) newState.contractNumInfo(tokenAReservedKey) shouldEqual 1100L - val tokenBReservedKey = ByteStr(Bytes.concat(vswapContractId.arr, Array(7.toByte))) //tokenAReservedStateVar newState.contractNumInfo(tokenBReservedKey) shouldEqual 910L + newState.contractNumInfo(totalSupplyKey) shouldEqual 1000L + newState.contractNumInfo(liquidityTokenLeft) shouldEqual 9000L + + newState.contractNumInfo(masterStateMapTokenABalanceKey) shouldEqual 900L + newState.contractNumInfo(masterStateMapTokenBBalanceKey) shouldEqual 1090L + newState.contractNumInfo(masterStateMapLiquidityTokenBalanceKey) shouldEqual 990L } } } From 4f9b4dc4faf8b821194c34684b7f7d3b31a292e7 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 7 Jan 2021 13:40:36 +0800 Subject: [PATCH 166/391] add set order --- .../contract/ContractVStableSwap.scala | 72 +++++++++++++++---- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index e40639f55..8ec27aed2 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -1,6 +1,6 @@ package vsys.blockchain.contract -import com.google.common.primitives.Ints +import com.google.common.primitives.{Ints, Longs} import vsys.blockchain.contract.ContractGen._ import vsys.blockchain.state._ import vsys.utils.serialization.Deser @@ -30,6 +30,7 @@ object ContractVStableSwap { val stateMapBaseTokenBalance = List("baseTokenBalance", "userAddress", "balance") val stateMapTargetTokenBalance = List("targetTokenBalance", "userAddress", "balance") val stateMapUserOrders = List("userOrders", "userAddress", "orderNum") + val stateMapOrderOwner = List("orderOwner", "orderId", "owner") val stateMapFeeBase = List("feeBase", "orderId", "fee") val stateMapFeeTarget = List("feeTarget", "orderId", "fee") val stateMapMinBase = List("minBase", "orderId", "amount") @@ -38,24 +39,33 @@ object ContractVStableSwap { val stateMapMaxTarget = List("maxTarget", "orderId", "amount") val stateMapPriceBase = List("priceBase", "orderId", "price") val stateMapPriceTarget = List("priceTarget", "orderId", "price") + val stateMapBaseTokenLocked = List("baseTokenLocked", "orderId", "amount") + val stateMapTargetTokenLocked = List("targetTokenLocked", "orderId", "amount") + val stateMapOrderStatus = List("orderStatus", "orderId", "status") val baseTokenBalanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) val targetTokenBalanceMap: StateMap = StateMap(1.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) val userOrdersMap: StateMap = StateMap(2.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) - val feeBaseMap: StateMap = StateMap(3.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) - val feeTargetMap: StateMap = StateMap(4.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) - val minBaseMap: StateMap = StateMap(5.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) - val maxBaseMap: StateMap = StateMap(6.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) - val minTargetMap: StateMap = StateMap(7.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) - val maxTargetMap: StateMap = StateMap(8.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) - val priceBaseMap: StateMap = StateMap(9.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) - val priceTargetMap: StateMap = StateMap(10.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderOwnerMap: StateMap = StateMap(3.toByte, DataType.ShortBytes.id.toByte, DataType.Address.id.toByte) + val feeBaseMap: StateMap = StateMap(4.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val feeTargetMap: StateMap = StateMap(5.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val minBaseMap: StateMap = StateMap(6.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val maxBaseMap: StateMap = StateMap(7.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val minTargetMap: StateMap = StateMap(8.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val maxTargetMap: StateMap = StateMap(9.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val priceBaseMap: StateMap = StateMap(10.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val priceTargetMap: StateMap = StateMap(11.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val baseTokenLockedMap: StateMap = StateMap(12.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val targetTokenLockedMap: StateMap = StateMap(13.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderStatusMap: StateMap = StateMap(14.toByte, DataType.ShortBytes.id.toByte, DataType.Boolean.id.toByte) - lazy val stateMapSeq = Seq(baseTokenBalanceMap.arr, targetTokenBalanceMap.arr, userOrdersMap.arr, + lazy val stateMapSeq = Seq(baseTokenBalanceMap.arr, targetTokenBalanceMap.arr, userOrdersMap.arr, orderOwnerMap.arr, feeBaseMap.arr, feeTargetMap.arr, minBaseMap.arr, maxBaseMap.arr, - minTargetMap.arr, maxTargetMap.arr, priceBaseMap.arr, priceTargetMap.arr) + minTargetMap.arr, maxTargetMap.arr, priceBaseMap.arr, priceTargetMap.arr, + baseTokenLockedMap.arr, targetTokenLockedMap.arr, orderStatusMap.arr) lazy val stateMapTextual: Array[Byte] = textualStateMap( - Seq(stateMapBaseTokenBalance, stateMapTargetTokenBalance, stateMapUserOrders, stateMapFeeBase, stateMapFeeTarget, - stateMapMinBase, stateMapMaxBase, stateMapMinTarget, stateMapMaxTarget, stateMapPriceBase, stateMapPriceTarget)) + Seq(stateMapBaseTokenBalance, stateMapTargetTokenBalance, stateMapUserOrders, stateMapOrderOwner, + stateMapFeeBase, stateMapFeeTarget, stateMapMinBase, stateMapMaxBase, stateMapMinTarget, + stateMapMaxTarget, stateMapPriceBase, stateMapPriceTarget, stateMapBaseTokenLocked, stateMapTargetTokenLocked, stateMapOrderStatus)) // Initialization Trigger val initId: Short = 0 @@ -145,13 +155,47 @@ object ContractVStableSwap { val supersedePara: Seq[String] = Seq("newOwner", "maker") val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte) - val supersedeOpcs: Seq[Array[Byte]] = Seq( + val supersedeOpcs: Seq[Array[Byte]] = Seq( cdbvrGet ++ Array(makerStateVar.index, 1.toByte), assertSigner ++ Array(1.toByte), cdbvSet ++ Array(makerStateVar.index, 0.toByte)) lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) val supersedeTextualBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) + // Set Order + val setOrderId: Short = 1 + val setOrderPara: Seq[String] = Seq("feeBase", "feeTarget", "minBase", "maxBase", "minTarget", "maxTarget", "priceBase", + "priceTarget", "baseDeposit", "targetDeposit") ++ + Seq("caller", "maxOrderPerUser", "userOrders", "isValidOrderNum", "orderId", "amountOne", "valueTrue") + val setOrderDataType: Array[Byte] = Array.fill[Byte](10)(DataType.Amount.id.toByte) + val setOrderOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(10.toByte), + cdbvrGet ++ Array(maxOrderPerUserStateVar.index, 11.toByte), + cdbvrMapGetOrDefault ++ Array(userOrdersMap.index, 10.toByte, 12.toByte), + compareGreater ++ Array(11.toByte, 12.toByte, 13.toByte), + assertTrue ++ Array(13.toByte), + loadTransactionId ++ Array(14.toByte), + cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 9.toByte), + cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 10.toByte), + cdbvMapSet ++ Array(orderOwnerMap.index, 14.toByte, 10.toByte), + cdbvMapSet ++ Array(feeBaseMap.index, 14.toByte, 0.toByte), + cdbvMapSet ++ Array(feeTargetMap.index, 14.toByte, 1.toByte), + cdbvMapSet ++ Array(minBaseMap.index, 14.toByte, 2.toByte), + cdbvMapSet ++ Array(maxBaseMap.index, 14.toByte, 3.toByte), + cdbvMapSet ++ Array(minTargetMap.index, 14.toByte, 4.toByte), + cdbvMapSet ++ Array(maxTargetMap.index, 14.toByte, 5.toByte), + cdbvMapSet ++ Array(priceBaseMap.index, 14.toByte, 6.toByte), + cdbvMapSet ++ Array(priceTargetMap.index, 14.toByte, 7.toByte), + cdbvMapValAdd ++ Array(baseTokenLockedMap.index, 14.toByte, 8.toByte), + cdbvMapValAdd ++ Array(targetTokenLockedMap.index, 14.toByte, 9.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1L), DataType.Amount).bytes ++ Array(15.toByte), + cdbvMapValAdd ++ Array(userOrdersMap.index, 10.toByte, 15.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(16.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 14.toByte, 16.toByte) + ) + lazy val setOrderFunc: Array[Byte] = getFunctionBytes(setOrderId, publicFuncType, nonReturnType, setOrderDataType, setOrderOpcs) + val setOrderTextualBytes: Array[Byte] = textualFunc("setOrder", Seq(), setOrderPara) + // Textual } \ No newline at end of file From e0555ab72101812321f09bbc45c8d3941588cac6 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 7 Jan 2021 13:42:05 +0800 Subject: [PATCH 167/391] remove lock icon --- src/main/scala/vsys/api/http/contract/ContractApiRoute.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 82adb90ab..9ddb43e0b 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -102,7 +102,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx } @Path("/data/{contractId}/{key}") - @ApiOperation(value = "Contract Data", notes = "Contract data by given contract ID and key (default numerical 0).", httpMethod = "Get", authorizations = Array(new Authorization("api_key"))) + @ApiOperation(value = "Contract Data", notes = "Contract data by given contract ID and key (default numerical 0).", httpMethod = "Get") @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract Account", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "key", value = "Key", required = true, dataType = "string", paramType = "path") From 486f97edde07d7f3da9c43736a0e2b431f0019c3 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Fri, 8 Jan 2021 09:56:57 +0800 Subject: [PATCH 168/391] move db key functions to helper functions --- .../vswap/VSwapFunctionHelperGen.scala | 48 ++++++++++++++++++- .../vswap/ExecuteVSwapValidDiffTest.scala | 47 +----------------- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala index 6d5f3c329..9940002d6 100644 --- a/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vswap/VSwapFunctionHelperGen.scala @@ -1,12 +1,13 @@ package vsys.blockchain.contract.vswap -import com.google.common.primitives.{Ints, Longs} +import com.google.common.primitives.{Bytes, Ints, Longs} import org.scalacheck.Gen import vsys.account.ContractAccount.tokenIdFromBytes -import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.account.{Address, ContractAccount, PrivateKeyAccount, PublicKeyAccount} import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.token.TokenContractGen import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.state.ByteStr import vsys.blockchain.transaction.GenesisTransaction import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} @@ -116,4 +117,47 @@ trait VSwapFunctionHelperGen extends VSwapContractGen with TokenContractGen { depositLiquidity <- depositToken(master, liquidityTokenContractId, master.toAddress.bytes.arr, vSwapContractId.bytes.arr, liquidityTotalSupply, fee + 10000000000L, ts + 9) } yield (genesis, genesis2, master, user, regTokenAContract, regTokenBContract, regLiquidityTokenContract, regVSwapContract, issueTokenA, issueTokenB, issueLiquidityToken, depositTokenA, depositTokenB, depositLiquidity, fee, ts, attach) + + def getContractTokenBalanceKeys(tokenAContractId: Array[Byte], tokenBContractId: Array[Byte], liquidityContractId: Array[Byte], vSwapContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr) = { + val tokenAId = tokenIdFromBytes(tokenAContractId, Ints.toByteArray(0)).explicitGet() + val tokenBId = tokenIdFromBytes(tokenBContractId, Ints.toByteArray(0)).explicitGet() + val liquidityTokenId = tokenIdFromBytes(liquidityContractId, Ints.toByteArray(0)).explicitGet() + + val contractTokenABalanceKey = ByteStr(Bytes.concat(tokenAId.arr, vSwapContractId)) + val contractTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, vSwapContractId)) + val contractLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, vSwapContractId)) + + (contractTokenABalanceKey, contractTokenBBalanceKey, contractLiquidityBalanceKey) + } + + def getUserTokenBalanceKeys(tokenAContractId: Array[Byte], tokenBContractId: Array[Byte], liquidityContractId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr) = { + val tokenAId = tokenIdFromBytes(tokenAContractId, Ints.toByteArray(0)).explicitGet() + val tokenBId = tokenIdFromBytes(tokenBContractId, Ints.toByteArray(0)).explicitGet() + val liquidityTokenId = tokenIdFromBytes(liquidityContractId, Ints.toByteArray(0)).explicitGet() + + val masterTokenABalanceKey = ByteStr(Bytes.concat(tokenAId.arr, user.toAddress.bytes.arr)) + val masterTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, user.toAddress.bytes.arr)) + val masterLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, user.toAddress.bytes.arr)) + + (masterTokenABalanceKey, masterTokenBBalanceKey, masterLiquidityBalanceKey) + } + + def getSwapContractStateVarKeys(vSwapContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr) = { + val swapStatusKey = ByteStr(Bytes.concat(vSwapContractId, Array(4.toByte))) + val minimumLiquidityKey = ByteStr(Bytes.concat(vSwapContractId, Array(5.toByte))) + val tokenAReservedKey = ByteStr(Bytes.concat(vSwapContractId, Array(6.toByte))) + val tokenBReservedKey = ByteStr(Bytes.concat(vSwapContractId, Array(7.toByte))) + val totalSupplyKey = ByteStr(Bytes.concat(vSwapContractId, Array(8.toByte))) + val liquidityTokenLeft = ByteStr(Bytes.concat(vSwapContractId, Array(9.toByte))) + + (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) + } + + def getSwapContractStateMapKeys(vSwapContractId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr) = { + val stateMapTokenABalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(0.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val stateMapTokenBBalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(1.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val stateMapLiquidityTokenBalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(2.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + + (stateMapTokenABalanceKey, stateMapTokenBBalanceKey, stateMapLiquidityTokenBalanceKey) + } } diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala index fc118e63d..6bb8d91a8 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala @@ -3,7 +3,6 @@ package vsys.blockchain.state.contract.vswap import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} -import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} @@ -12,8 +11,7 @@ import vsys.blockchain.state.diffs._ import vsys.blockchain.transaction.contract._ import vsys.blockchain.state._ import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} -import com.google.common.primitives.{Bytes, Ints, Longs} -import vsys.account.PublicKeyAccount +import com.google.common.primitives.Longs class ExecuteVSwapValidDiffTest extends PropSpec with PropertyChecks @@ -27,49 +25,6 @@ class ExecuteVSwapValidDiffTest extends PropSpec private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) - def getContractTokenBalanceKeys(tokenAContractId: Array[Byte], tokenBContractId: Array[Byte], liquidityContractId: Array[Byte], vSwapContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr) = { - val tokenAId = tokenIdFromBytes(tokenAContractId, Ints.toByteArray(0)).explicitGet() - val tokenBId = tokenIdFromBytes(tokenBContractId, Ints.toByteArray(0)).explicitGet() - val liquidityTokenId = tokenIdFromBytes(liquidityContractId, Ints.toByteArray(0)).explicitGet() - - val contractTokenABalanceKey = ByteStr(Bytes.concat(tokenAId.arr, vSwapContractId)) - val contractTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, vSwapContractId)) - val contractLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, vSwapContractId)) - - (contractTokenABalanceKey, contractTokenBBalanceKey, contractLiquidityBalanceKey) - } - - def getUserTokenBalanceKeys(tokenAContractId: Array[Byte], tokenBContractId: Array[Byte], liquidityContractId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr) = { - val tokenAId = tokenIdFromBytes(tokenAContractId, Ints.toByteArray(0)).explicitGet() - val tokenBId = tokenIdFromBytes(tokenBContractId, Ints.toByteArray(0)).explicitGet() - val liquidityTokenId = tokenIdFromBytes(liquidityContractId, Ints.toByteArray(0)).explicitGet() - - val masterTokenABalanceKey = ByteStr(Bytes.concat(tokenAId.arr, user.toAddress.bytes.arr)) - val masterTokenBBalanceKey = ByteStr(Bytes.concat(tokenBId.arr, user.toAddress.bytes.arr)) - val masterLiquidityBalanceKey = ByteStr(Bytes.concat(liquidityTokenId.arr, user.toAddress.bytes.arr)) - - (masterTokenABalanceKey, masterTokenBBalanceKey, masterLiquidityBalanceKey) - } - - def getSwapContractStateVarKeys(vSwapContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr) = { - val swapStatusKey = ByteStr(Bytes.concat(vSwapContractId, Array(4.toByte))) - val minimumLiquidityKey = ByteStr(Bytes.concat(vSwapContractId, Array(5.toByte))) - val tokenAReservedKey = ByteStr(Bytes.concat(vSwapContractId, Array(6.toByte))) - val tokenBReservedKey = ByteStr(Bytes.concat(vSwapContractId, Array(7.toByte))) - val totalSupplyKey = ByteStr(Bytes.concat(vSwapContractId, Array(8.toByte))) - val liquidityTokenLeft = ByteStr(Bytes.concat(vSwapContractId, Array(9.toByte))) - - (swapStatusKey, minimumLiquidityKey, tokenAReservedKey, tokenBReservedKey, totalSupplyKey, liquidityTokenLeft) - } - - def getSwapContractStateMapKeys(vSwapContractId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr) = { - val stateMapTokenABalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(0.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) - val stateMapTokenBBalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(1.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) - val stateMapLiquidityTokenBalanceKey = ByteStr(Bytes.concat(vSwapContractId, Array(2.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) - - (stateMapTokenABalanceKey, stateMapTokenBBalanceKey, stateMapLiquidityTokenBalanceKey) - } - val preconditionsAndVSwapDepositAndWithdrawLiquidityTokens: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, From 2e9141821528457f1056dcf6504889638b204485 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 12 Jan 2021 10:52:51 +0800 Subject: [PATCH 169/391] add update order func --- .../contract/ContractVStableSwap.scala | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 8ec27aed2..99c9eae09 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -196,6 +196,28 @@ object ContractVStableSwap { lazy val setOrderFunc: Array[Byte] = getFunctionBytes(setOrderId, publicFuncType, nonReturnType, setOrderDataType, setOrderOpcs) val setOrderTextualBytes: Array[Byte] = textualFunc("setOrder", Seq(), setOrderPara) + // Update Order + val updateId: Short = 2 + val updatePara: Seq[String] = Seq("orderId", "feeBase", "feeTarget", "minBase", "maxBase", "minTarget", "maxTarget", + "priceBase", "priceTarget") ++ + Seq("owner", "status") + val updateDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) ++ Array.fill[Byte](8)(DataType.Amount.id.toByte) + val updateOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, 9.toByte), + assertCaller ++ Array(9.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 10.toByte), + assertTrue ++ Array(10.toByte), + cdbvMapSet ++ Array(feeBaseMap.index, 0.toByte, 1.toByte), + cdbvMapSet ++ Array(feeTargetMap.index, 0.toByte, 2.toByte), + cdbvMapSet ++ Array(minBaseMap.index, 0.toByte, 3.toByte), + cdbvMapSet ++ Array(maxBaseMap.index, 0.toByte, 4.toByte), + cdbvMapSet ++ Array(minTargetMap.index, 0.toByte, 5.toByte), + cdbvMapSet ++ Array(maxTargetMap.index, 0.toByte, 6.toByte), + cdbvMapSet ++ Array(priceBaseMap.index, 0.toByte, 7.toByte), + cdbvMapSet ++ Array(priceTargetMap.index, 0.toByte, 8.toByte) + ) + lazy val updateFunc: Array[Byte] = getFunctionBytes(updateId, publicFuncType, nonReturnType, updateDataType, updateOpcs) + val updateTextualBytes: Array[Byte] = textualFunc("update", Seq(), updatePara) // Textual } \ No newline at end of file From 977743acfeb2469cddcf7888d80e13af81aa1814 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 12 Jan 2021 11:03:23 +0800 Subject: [PATCH 170/391] add order deposit --- .../contract/ContractVStableSwap.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 99c9eae09..5bed9e184 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -218,6 +218,24 @@ object ContractVStableSwap { ) lazy val updateFunc: Array[Byte] = getFunctionBytes(updateId, publicFuncType, nonReturnType, updateDataType, updateOpcs) val updateTextualBytes: Array[Byte] = textualFunc("update", Seq(), updatePara) + + // Order Deposit + val orderDepositId: Short = 3 + val orderDepositPara: Seq[String] = Seq("orderId", "baseDeposit", "targetDeposit")++ + Seq("owner", "status") + val orderDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) + val orderDepositOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, 3.toByte), + assertCaller ++ Array(3.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte), + assertTrue ++ Array(4.toByte), + cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 3.toByte, 1.toByte), + cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 3.toByte, 2.toByte), + cdbvMapValAdd ++ Array(baseTokenLockedMap.index, 0.toByte, 1.toByte), + cdbvMapValAdd ++ Array(targetTokenLockedMap.index, 0.toByte, 2.toByte) + ) + lazy val orderDepositFunc: Array[Byte] = getFunctionBytes(orderDepositId, publicFuncType, nonReturnType, orderDepositDataType, orderDepositOpcs) + val OrderDepositTextualBytes: Array[Byte] = textualFunc("orderDeposit", Seq(), orderDepositPara) // Textual } \ No newline at end of file From 20d6c8d0e7ee65b5dc290cfc0b38271f8518e426 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 12 Jan 2021 11:06:10 +0800 Subject: [PATCH 171/391] add order withdraw --- .../contract/ContractVStableSwap.scala | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 5bed9e184..64aa45f3d 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -221,7 +221,7 @@ object ContractVStableSwap { // Order Deposit val orderDepositId: Short = 3 - val orderDepositPara: Seq[String] = Seq("orderId", "baseDeposit", "targetDeposit")++ + val orderDepositPara: Seq[String] = Seq("orderId", "baseDeposit", "targetDeposit") ++ Seq("owner", "status") val orderDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) val orderDepositOpcs: Seq[Array[Byte]] = Seq( @@ -236,6 +236,24 @@ object ContractVStableSwap { ) lazy val orderDepositFunc: Array[Byte] = getFunctionBytes(orderDepositId, publicFuncType, nonReturnType, orderDepositDataType, orderDepositOpcs) val OrderDepositTextualBytes: Array[Byte] = textualFunc("orderDeposit", Seq(), orderDepositPara) + + // Order Withdraw + val orderWithdrawId: Short = 4 + val orderWithdrawPara: Seq[String] = Seq("orderId", "baseWithdraw", "targetWithdraw")++ + Seq("owner", "status") + val orderWithdrawDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) + val orderWithdrawOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, 3.toByte), + assertCaller ++ Array(3.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte), + assertTrue ++ Array(4.toByte), + cdbvMapValMinus ++ Array(baseTokenLockedMap.index, 0.toByte, 1.toByte), + cdbvMapValMinus ++ Array(targetTokenLockedMap.index, 0.toByte, 2.toByte), + cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 3.toByte, 1.toByte), + cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 3.toByte, 2.toByte) + ) + lazy val orderWithdrawFunc: Array[Byte] = getFunctionBytes(orderWithdrawId, publicFuncType, nonReturnType, orderWithdrawDataType, orderWithdrawOpcs) + val OrderWithdrawTextualBytes: Array[Byte] = textualFunc("orderWithdraw", Seq(), orderWithdrawPara) // Textual } \ No newline at end of file From 45292b00c631830ecae79536c09a6ba7b893bdbb Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 12 Jan 2021 11:18:24 +0800 Subject: [PATCH 172/391] add close order func --- .../contract/ContractVStableSwap.scala | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 64aa45f3d..d695bc44c 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -239,7 +239,7 @@ object ContractVStableSwap { // Order Withdraw val orderWithdrawId: Short = 4 - val orderWithdrawPara: Seq[String] = Seq("orderId", "baseWithdraw", "targetWithdraw")++ + val orderWithdrawPara: Seq[String] = Seq("orderId", "baseWithdraw", "targetWithdraw") ++ Seq("owner", "status") val orderWithdrawDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) val orderWithdrawOpcs: Seq[Array[Byte]] = Seq( @@ -253,7 +253,31 @@ object ContractVStableSwap { cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 3.toByte, 2.toByte) ) lazy val orderWithdrawFunc: Array[Byte] = getFunctionBytes(orderWithdrawId, publicFuncType, nonReturnType, orderWithdrawDataType, orderWithdrawOpcs) - val OrderWithdrawTextualBytes: Array[Byte] = textualFunc("orderWithdraw", Seq(), orderWithdrawPara) + val orderWithdrawTextualBytes: Array[Byte] = textualFunc("orderWithdraw", Seq(), orderWithdrawPara) + + // Order Close + val closeId: Short = 5 + val closePara: Seq[String] = Seq("orderId") ++ + Seq("owner", "status", "baseWithdraw", "targetWithdraw", "amountOne", "valueFalse") + val closeDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + val closeOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, 1.toByte), + assertCaller ++ Array(1.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), + assertTrue ++ Array(2.toByte), + cdbvrMapGetOrDefault ++ Array(baseTokenLockedMap.index, 0.toByte, 3.toByte), + cdbvrMapGetOrDefault ++ Array(targetTokenLockedMap.index, 0.toByte, 4.toByte), + cdbvMapValMinus ++ Array(baseTokenLockedMap.index, 0.toByte, 3.toByte), + cdbvMapValMinus ++ Array(targetTokenLockedMap.index, 0.toByte, 4.toByte), + cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 1.toByte, 3.toByte), + cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 1.toByte, 4.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1L), DataType.Amount).bytes ++ Array(5.toByte), + cdbvMapValMinus ++ Array(userOrdersMap.index, 1.toByte, 5.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 6.toByte) + ) + lazy val closeFunc: Array[Byte] = getFunctionBytes(closeId, publicFuncType, nonReturnType, closeDataType, closeOpcs) + val closeTextualBytes: Array[Byte] = textualFunc("close", Seq(), closePara) // Textual } \ No newline at end of file From 9c8def2e257f78ac58709d20bdcf33eb3ae4688b Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 12 Jan 2021 11:25:41 +0800 Subject: [PATCH 173/391] add common check opcs --- .../contract/ContractVStableSwap.scala | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index d695bc44c..898b70ffe 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -196,17 +196,20 @@ object ContractVStableSwap { lazy val setOrderFunc: Array[Byte] = getFunctionBytes(setOrderId, publicFuncType, nonReturnType, setOrderDataType, setOrderOpcs) val setOrderTextualBytes: Array[Byte] = textualFunc("setOrder", Seq(), setOrderPara) + private def commonCheckOpcs(ownerIndex: Byte, statusIndex: Byte): Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, ownerIndex), + assertCaller ++ Array(ownerIndex), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, statusIndex), + assertTrue ++ Array(statusIndex) + ) + // Update Order val updateId: Short = 2 val updatePara: Seq[String] = Seq("orderId", "feeBase", "feeTarget", "minBase", "maxBase", "minTarget", "maxTarget", "priceBase", "priceTarget") ++ Seq("owner", "status") val updateDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) ++ Array.fill[Byte](8)(DataType.Amount.id.toByte) - val updateOpcs: Seq[Array[Byte]] = Seq( - cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, 9.toByte), - assertCaller ++ Array(9.toByte), - cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 10.toByte), - assertTrue ++ Array(10.toByte), + val updateOpcs: Seq[Array[Byte]] = commonCheckOpcs(9.toByte, 10.toByte) ++ Seq( cdbvMapSet ++ Array(feeBaseMap.index, 0.toByte, 1.toByte), cdbvMapSet ++ Array(feeTargetMap.index, 0.toByte, 2.toByte), cdbvMapSet ++ Array(minBaseMap.index, 0.toByte, 3.toByte), @@ -222,13 +225,9 @@ object ContractVStableSwap { // Order Deposit val orderDepositId: Short = 3 val orderDepositPara: Seq[String] = Seq("orderId", "baseDeposit", "targetDeposit") ++ - Seq("owner", "status") + Seq("owner", "status") val orderDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) - val orderDepositOpcs: Seq[Array[Byte]] = Seq( - cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, 3.toByte), - assertCaller ++ Array(3.toByte), - cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte), - assertTrue ++ Array(4.toByte), + val orderDepositOpcs: Seq[Array[Byte]] = commonCheckOpcs(3.toByte, 4.toByte) ++ Seq( cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 3.toByte, 1.toByte), cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 3.toByte, 2.toByte), cdbvMapValAdd ++ Array(baseTokenLockedMap.index, 0.toByte, 1.toByte), @@ -242,11 +241,7 @@ object ContractVStableSwap { val orderWithdrawPara: Seq[String] = Seq("orderId", "baseWithdraw", "targetWithdraw") ++ Seq("owner", "status") val orderWithdrawDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) - val orderWithdrawOpcs: Seq[Array[Byte]] = Seq( - cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, 3.toByte), - assertCaller ++ Array(3.toByte), - cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte), - assertTrue ++ Array(4.toByte), + val orderWithdrawOpcs: Seq[Array[Byte]] = commonCheckOpcs(3.toByte, 4.toByte) ++ Seq( cdbvMapValMinus ++ Array(baseTokenLockedMap.index, 0.toByte, 1.toByte), cdbvMapValMinus ++ Array(targetTokenLockedMap.index, 0.toByte, 2.toByte), cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 3.toByte, 1.toByte), @@ -260,11 +255,7 @@ object ContractVStableSwap { val closePara: Seq[String] = Seq("orderId") ++ Seq("owner", "status", "baseWithdraw", "targetWithdraw", "amountOne", "valueFalse") val closeDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) - val closeOpcs: Seq[Array[Byte]] = Seq( - cdbvrMapGet ++ Array(orderOwnerMap.index, 0.toByte, 1.toByte), - assertCaller ++ Array(1.toByte), - cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), - assertTrue ++ Array(2.toByte), + val closeOpcs: Seq[Array[Byte]] = commonCheckOpcs(1.toByte, 2.toByte) ++ Seq( cdbvrMapGetOrDefault ++ Array(baseTokenLockedMap.index, 0.toByte, 3.toByte), cdbvrMapGetOrDefault ++ Array(targetTokenLockedMap.index, 0.toByte, 4.toByte), cdbvMapValMinus ++ Array(baseTokenLockedMap.index, 0.toByte, 3.toByte), From ecb5303a064beb747411447f17bed017fffe4cb7 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Wed, 13 Jan 2021 14:45:07 +0800 Subject: [PATCH 174/391] Add VOptionContractGen --- .../contract/voption/VOptionContractGen.scala | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/voption/VOptionContractGen.scala diff --git a/src/test/scala/vsys/blockchain/contract/voption/VOptionContractGen.scala b/src/test/scala/vsys/blockchain/contract/voption/VOptionContractGen.scala new file mode 100644 index 000000000..cb0c99dfd --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/voption/VOptionContractGen.scala @@ -0,0 +1,148 @@ +package vsys.blockchain.contract.voption + +import com.google.common.primitives.Longs +import org.scalacheck.Gen +import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.{Contract, ContractVOption, DataEntry, DataType} +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.state._ +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +trait VOptionContractGen { + + val supersedeIndex: Short = 0 + val activateIndex: Short = 1 + val mintIndex: Short = 2 + val unlockIndex: Short = 3 + val executeIndex: Short = 4 + val collectIndex: Short = 5 + + def vOptionContractGen(): Gen[Contract] = ContractVOption.contract + + def genesisVOptionGen(rep: PrivateKeyAccount, + ts: Long): Gen[GenesisTransaction] = + GenesisTransaction.create(rep, ENOUGH_AMT, -1, ts).explicitGet() + + def registerVOptionGen(signer: PrivateKeyAccount, + contract: Contract, + dataStack: Seq[DataEntry], + description: String, + fee: Long, + ts: Long): Gen[RegisterContractTransaction] = + RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() + + def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + addr <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) + } yield Seq(addr) + + def activateDataStackGen(maxIssueNum: Long, + price: Long, + priceUnit: Long): Gen[Seq[DataEntry]] = for { + maxIssueNum <- Gen.const(DataEntry(Longs.toByteArray(maxIssueNum), DataType.Amount)) + price <- Gen.const(DataEntry(Longs.toByteArray(price), DataType.Amount)) + priceUnit <- Gen.const(DataEntry(Longs.toByteArray(priceUnit), DataType.Amount)) + } yield Seq(maxIssueNum, price, priceUnit) + + def commonOptionDataStackGen(amount: Long): Gen[Seq[DataEntry]] = for { + amount <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) + } yield Seq(amount) + + def initVOptionDataStackGen(baseTokenId: Array[Byte], + targetTokenId: Array[Byte], + optionTokenId: Array[Byte], + proofTokenId: Array[Byte], + executeTime: Long, + executeDeadLine: Long): Gen[Seq[DataEntry]] = { + for { + baseTokenId <- Gen.const(DataEntry.create(baseTokenId, DataType.TokenId).right.get) + targetTokenId <- Gen.const(DataEntry.create(targetTokenId, DataType.TokenId).right.get) + optionTokenId <- Gen.const(DataEntry.create(optionTokenId, DataType.TokenId).right.get) + proofTokenId <- Gen.const(DataEntry.create(proofTokenId, DataType.TokenId).right.get) + executeTime <- Gen.const(DataEntry.create(Longs.toByteArray(executeTime), DataType.Timestamp).right.get) + executeDeadLine <- Gen.const(DataEntry.create(Longs.toByteArray(executeDeadLine), DataType.Timestamp).right.get) + } yield Seq(baseTokenId, targetTokenId, optionTokenId, proofTokenId, executeTime, executeDeadLine) + } + + + def supersedeVOptionGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + newAddr: Address, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = supersedeIndex + for { + data: Seq[DataEntry] <- addressDataStackGen(newAddr) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def activateVOptionGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + maxIssueNum: Long, + price: Long, + priceUnit: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = activateIndex + for { + data <- activateDataStackGen(maxIssueNum, price, priceUnit) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def mintVOptionGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + amount: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = mintIndex + for { + data <- commonOptionDataStackGen(amount) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def unlockVOptionGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + amount: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = unlockIndex + for { + data <- commonOptionDataStackGen(amount) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def executeVOptionGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + amount: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = executeIndex + for { + data <- commonOptionDataStackGen(amount) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def collectVOptionGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + amount: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = collectIndex + for { + data <- commonOptionDataStackGen(amount) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + +} \ No newline at end of file From 1764f3e65dc92b9bd3385c93f47ac2a358be5edc Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Wed, 13 Jan 2021 15:11:10 +0800 Subject: [PATCH 175/391] Add VOptionFunction --- .../contract/voption/VOptionFunction.scala | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/voption/VOptionFunction.scala diff --git a/src/test/scala/vsys/blockchain/contract/voption/VOptionFunction.scala b/src/test/scala/vsys/blockchain/contract/voption/VOptionFunction.scala new file mode 100644 index 000000000..b54511b3f --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/voption/VOptionFunction.scala @@ -0,0 +1,46 @@ +package vsys.blockchain.contract.voption + +import vsys.blockchain.contract.ContractGen.{basicConstantGet, cdbvSet, getFunctionBytes, loadSigner} +import vsys.blockchain.contract.ContractVOption.{baseTokenIdStateVar, executeDeadlineStateVar, executeTimeStateVar, makerStateVar, optionStatusStateVar, optionTokenIdStateVar, proofTokenIdStateVar, targetTokenIdStateVar} +import vsys.blockchain.contract.ContractVSwap._ +import vsys.blockchain.contract.{DataEntry, DataType} + +trait VOptionFunction { + + val initId: Short = 0 + + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.TokenId.id.toByte,DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.Timestamp.id.toByte, DataType.Timestamp.id.toByte) + val initWrongDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.TokenId.id.toByte,DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.Timestamp.id.toByte, DataType.Timestamp.id.toByte) + + val initTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(6.toByte), + cdbvSet ++ Array(makerStateVar.index, 6.toByte), + cdbvSet ++ Array(baseTokenIdStateVar.index, 0.toByte), + cdbvSet ++ Array(targetTokenIdStateVar.index, 1.toByte), + cdbvSet ++ Array(optionTokenIdStateVar.index, 2.toByte), + cdbvSet ++ Array(proofTokenIdStateVar.index, 3.toByte), + cdbvSet ++ Array(executeTimeStateVar.index, 4.toByte), + cdbvSet ++ Array(executeDeadlineStateVar.index, 5.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + cdbvSet ++ Array(optionStatusStateVar.index, 5.toByte) + ) + + val initWrongTriggerOpcs: Seq[Array[Byte]] = Seq( + Array(5.toByte, 3.toByte) ++ loadSigner ++ Array(6.toByte), + cdbvSet ++ Array(makerStateVar.index, 6.toByte), + cdbvSet ++ Array(baseTokenIdStateVar.index, 0.toByte), + cdbvSet ++ Array(targetTokenIdStateVar.index, 1.toByte), + cdbvSet ++ Array(optionTokenIdStateVar.index, 2.toByte), + cdbvSet ++ Array(proofTokenIdStateVar.index, 3.toByte), + cdbvSet ++ Array(executeTimeStateVar.index, 4.toByte), + cdbvSet ++ Array(executeDeadlineStateVar.index, 5.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), + cdbvSet ++ Array(optionStatusStateVar.index, 5.toByte) + ) + + val nonReturnType: Array[Byte] = Array[Byte]() + val onInitTriggerType: Byte = 0 + + lazy val wrongDataTrigger: Seq[Array[Byte]] = Seq(getFunctionBytes(initId, onInitTriggerType, nonReturnType, initWrongDataType, initTriggerOpcs)) + lazy val wrongOpcTrigger: Seq[Array[Byte]] = Seq(getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initWrongTriggerOpcs)) +} From b1fb5dd608beee290dc9146a73483b6e07fe57a8 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Wed, 13 Jan 2021 15:13:52 +0800 Subject: [PATCH 176/391] Add VOptionFunctionHelperGen --- .../voption/VOptionFunctionHelperGen.scala | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/voption/VOptionFunctionHelperGen.scala diff --git a/src/test/scala/vsys/blockchain/contract/voption/VOptionFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/voption/VOptionFunctionHelperGen.scala new file mode 100644 index 000000000..b89e9f1c7 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/voption/VOptionFunctionHelperGen.scala @@ -0,0 +1,193 @@ +package vsys.blockchain.contract.voption + +import com.google.common.primitives.{Bytes, Ints, Longs} +import org.scalacheck.Gen +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.account.{Address, ContractAccount, PrivateKeyAccount, PublicKeyAccount} +import vsys.blockchain.contract.{DataEntry, DataType} +import vsys.blockchain.contract.token.TokenContractGen +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.state.ByteStr +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +trait VOptionFunctionHelperGen extends VOptionContractGen with TokenContractGen { + + override val supersedeIndex: Short = 0 + + override def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + addr <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) + } yield Seq(addr) + + def registerToken(user: PrivateKeyAccount, + totalSupply: Long, + unity: Long, + desc: String, + fee: Long, + timestamp: Long): Gen[RegisterContractTransaction] = for { + initTokenDataStack: Seq[DataEntry] <- initTokenDataStackGen(totalSupply, unity, desc) + description <- validDescStringGen + tokenContract <- tokenContractGen(false) + regTokenContract <- registerTokenGen(user, tokenContract, initTokenDataStack, description, fee, timestamp) + } yield regTokenContract + + def issueToken(user: PrivateKeyAccount, + contractId: ContractAccount, + issueAmount: Long, + fee: Long, + timestamp: Long): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issueToken <- issueTokenGen(user, contractId, issueAmount, attach, fee, timestamp) + } yield issueToken + + def depositToken(user: PrivateKeyAccount, + contractId: ContractAccount, + sender: Array[Byte], + contract: Array[Byte], + amount: Long, + fee: Long, + timestamp: Long + ): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + depositTokenData = Seq(sender, contract, Longs.toByteArray(amount)) + depositTokenDataType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + depositToken <- depositTokenGen(user, contractId, false, depositTokenData, depositTokenDataType, attach, fee, timestamp) + } yield depositToken + + def withdrawToken(user: PrivateKeyAccount, + contractId: ContractAccount, + contract: Array[Byte], + sender: Array[Byte], + amount: Long, + fee: Long, + timestamp: Long): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + withdrawTokenData = Seq(contract, sender, Longs.toByteArray(amount)) + withdrawTokenDataType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + withdrawToken <- withdrawTokenGen(user, contractId, false, withdrawTokenData, withdrawTokenDataType, attach, fee, timestamp) + } yield withdrawToken + + def createBaseTargetOptionProofTokenAndInitVOption(baseTotalSupply: Long, + baseUnity: Long, + baseIssueAmount: Long, + targetTotalSupply: Long, + targetUnity: Long, + targetIssueAmount: Long, + optionTotalSupply: Long, + optionUnity: Long, + proofTotalSupply: Long, + proofUnity: Long, + baseTokenDepositAmount: Long, + targetTokenDepositAmount: Long, + optionTokenDepositAmount: Long, + proofTokenDepositAmount: Long): Gen[(GenesisTransaction, GenesisTransaction, + PrivateKeyAccount, PrivateKeyAccount, RegisterContractTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long, Long, Array[Byte])] = for { + (master, ts, fee) <- basicContractTestGen() + + genesis <- genesisVOptionGen(master, ts) + user <- accountGen + genesis2 <- genesisVOptionGen(user, ts) + vOptionContract <- vOptionContractGen() + + // register base token + regBaseTokenContract <- registerToken(master, baseTotalSupply, baseUnity, "init", fee + 10000000000L, ts) + baseTokenContractId = regBaseTokenContract.contractId + baseTokenId = tokenIdFromBytes(baseTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register target token + regTargetTokenContract <- registerToken(master, targetTotalSupply, targetUnity, "init", fee + 10000000000L, ts + 1) + targetTokenContractId = regTargetTokenContract.contractId + targetTokenId = tokenIdFromBytes(targetTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register option token + regOptionTokenContract <- registerToken(master, optionTotalSupply, optionUnity, "init", fee + 10000000000L, ts + 2) + optionTokenContractId = regOptionTokenContract.contractId + optionTokenId = tokenIdFromBytes(optionTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register proof token + regProofTokenContract <- registerToken(master, proofTotalSupply, proofUnity, "init", fee + 10000000000L, ts + 3) + proofTokenContractId = regProofTokenContract.contractId + proofTokenId = tokenIdFromBytes(proofTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + // register VSwap contract + description <- validDescStringGen + initVOptionDataStack: Seq[DataEntry] <- initVOptionDataStackGen(baseTokenId.arr, targetTokenId.arr, optionTokenId.arr, proofTokenId.arr, ts + 100, ts + 200) + regVOptionContract <- registerVOptionGen(master, vOptionContract, initVOptionDataStack, description, fee + 10000000000L, ts + 4) + vOptionContractId = regVOptionContract.contractId + + // issue base token + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issueBaseToken <- issueToken(master, baseTokenContractId, baseIssueAmount, fee, ts + 5) + // issue target token + issueTargetToken <- issueToken(master, targetTokenContractId, targetIssueAmount, fee, ts + 6) + // issue option token, always issue the entire supply of option tokens + issueOptionToken <- issueToken(master, optionTokenContractId, optionTotalSupply, fee, ts + 7) + // issue proof token, always issue the entire supply of proof tokens + issueProofToken <- issueToken(master, proofTokenContractId, proofTotalSupply, fee, ts + 8) + + // deposit all issued tokens into voption contract, always deposit the entire supply of option and proof tokens + depositBaseToken <- depositToken(master, baseTokenContractId, master.toAddress.bytes.arr, vOptionContractId.bytes.arr, baseTokenDepositAmount, fee + 10000000000L, ts + 9) + depositTargetToken <- depositToken(master, targetTokenContractId, master.toAddress.bytes.arr, vOptionContractId.bytes.arr, targetTokenDepositAmount, fee + 10000000000L, ts + 10) + depositOptionToken <- depositToken(master, optionTokenContractId, master.toAddress.bytes.arr, vOptionContractId.bytes.arr, optionTokenDepositAmount, fee + 10000000000L, ts + 11) + depositProofToken <- depositToken(master, proofTokenContractId, master.toAddress.bytes.arr, vOptionContractId.bytes.arr, proofTokenDepositAmount, fee + 10000000000L, ts + 12) + } yield (genesis, genesis2, master, user, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken , depositProofToken, fee, ts, attach) + + def getOptionContractTokenBalanceKeys(baseTokenContractId: Array[Byte], + targetTokenContractId: Array[Byte], + optionTokenContractId: Array[Byte], + proofTokenContractId: Array[Byte], + vOptionContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr, ByteStr) = { + val baseTokenId = tokenIdFromBytes(baseTokenContractId, Ints.toByteArray(0)).explicitGet() + val targetTokenId = tokenIdFromBytes(targetTokenContractId, Ints.toByteArray(0)).explicitGet() + val optionTokenId = tokenIdFromBytes(optionTokenContractId, Ints.toByteArray(0)).explicitGet() + val proofTokenId = tokenIdFromBytes(proofTokenContractId, Ints.toByteArray(0)).explicitGet() + + val contractBaseTokenBalanceKey = ByteStr(Bytes.concat(baseTokenId.arr, vOptionContractId)) + val contractTargetTokenBalanceKey = ByteStr(Bytes.concat(targetTokenId.arr, vOptionContractId)) + val contractOptionTokenBalanceKey = ByteStr(Bytes.concat(optionTokenId.arr, vOptionContractId)) + val contractProofTokenBalanceKey = ByteStr(Bytes.concat(proofTokenId.arr, vOptionContractId)) + + (contractBaseTokenBalanceKey, contractTargetTokenBalanceKey, contractOptionTokenBalanceKey, contractProofTokenBalanceKey) + } + + def getOptionUserTokenBalanceKeys(baseTokenContractId: Array[Byte], + targetTokenContractId: Array[Byte], + optionTokenContractId: Array[Byte], + proofTokenContractId: Array[Byte], + user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr, ByteStr) = { + val baseTokenId = tokenIdFromBytes(baseTokenContractId, Ints.toByteArray(0)).explicitGet() + val targetTokenId = tokenIdFromBytes(targetTokenContractId, Ints.toByteArray(0)).explicitGet() + val optionTokenId = tokenIdFromBytes(optionTokenContractId, Ints.toByteArray(0)).explicitGet() + val proofTokenId = tokenIdFromBytes(proofTokenContractId, Ints.toByteArray(0)).explicitGet() + + val userBaseTokenBalanceKey = ByteStr(Bytes.concat(baseTokenId.arr, user.toAddress.bytes.arr)) + val userTargetTokenBalanceKey = ByteStr(Bytes.concat(targetTokenId.arr, user.toAddress.bytes.arr)) + val userOptionTokenBalanceKey = ByteStr(Bytes.concat(optionTokenId.arr, user.toAddress.bytes.arr)) + val userProofTokenBalanceKey = ByteStr(Bytes.concat(proofTokenId.arr, user.toAddress.bytes.arr)) + + (userBaseTokenBalanceKey, userTargetTokenBalanceKey, userOptionTokenBalanceKey, userProofTokenBalanceKey) + } + + def getOptionContractStateVarKeys(vOptionContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr) = { + val optionStatusKey = ByteStr(Bytes.concat(vOptionContractId, Array(7.toByte))) + val maxIssueNumKey = ByteStr(Bytes.concat(vOptionContractId, Array(8.toByte))) + val reservedOptionKey = ByteStr(Bytes.concat(vOptionContractId, Array(9.toByte))) + val reservedProofKey = ByteStr(Bytes.concat(vOptionContractId, Array(10.toByte))) + val priceKey = ByteStr(Bytes.concat(vOptionContractId, Array(11.toByte))) + val priceUnitKey = ByteStr(Bytes.concat(vOptionContractId, Array(12.toByte))) + val tokenLockedKey = ByteStr(Bytes.concat(vOptionContractId, Array(13.toByte))) + val tokenCollectedKey = ByteStr(Bytes.concat(vOptionContractId, Array(14.toByte))) + + (optionStatusKey, maxIssueNumKey, reservedOptionKey, reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) + } + + def getOptionContractStateMapKeys(vOptionContractId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr, ByteStr) = { + val stateMapBaseTokenBalanceKey = ByteStr(Bytes.concat(vOptionContractId, Array(0.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val stateMapTargetTokenBalanceKey = ByteStr(Bytes.concat(vOptionContractId, Array(1.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val stateMapOptionTokenBalanceKey = ByteStr(Bytes.concat(vOptionContractId, Array(2.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val stateMapProofTokenBalanceKey = ByteStr(Bytes.concat(vOptionContractId, Array(3.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + + (stateMapBaseTokenBalanceKey, stateMapTargetTokenBalanceKey, stateMapOptionTokenBalanceKey, stateMapProofTokenBalanceKey) + } +} From 4fa71884fbdb652b1fda3afd1173a53bddd24db5 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Wed, 13 Jan 2021 17:41:42 +0800 Subject: [PATCH 177/391] Add VOptionContractOpcDiffTest --- .../voption/VOptionContractOpcDiffTest.scala | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/voption/VOptionContractOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/VOptionContractOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/VOptionContractOpcDiffTest.scala new file mode 100644 index 000000000..12b59db76 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/voption/VOptionContractOpcDiffTest.scala @@ -0,0 +1,75 @@ +package vsys.blockchain.state.contract.voption + +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry} +import vsys.blockchain.contract.ContractVOption._ +import vsys.utils.serialization.Deser +import com.google.common.primitives.Ints +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount +import vsys.blockchain.contract.voption.{VOptionContractGen, VOptionFunction} +import vsys.blockchain.state._ +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidOPCData} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.blockchain.transaction.TransactionGen + +class VOptionContractOpcDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with VOptionContractGen + with VOptionFunction { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val regWrongOpcFunContract: Gen[Contract] = + Gen.const(Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + wrongOpcTrigger, + Seq(supersedeFunc, activateFunc, mintFunc, unlockFunc, executeFunc, collectFunc), + stateVarSeq, stateMapSeq, Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual)).explicitGet()) + + val regWrongDataContract: Gen[Contract] = + Gen.const(Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + wrongDataTrigger, + Seq(supersedeFunc, activateFunc, mintFunc, unlockFunc, executeFunc, collectFunc), + stateVarSeq, stateMapSeq, Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual)).explicitGet()) + + val validContract: Gen[Contract] = vOptionContractGen() + val preconditionsAndRegContractWrongFun: Gen[(RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + validContract <- validContract + wrongOpcContract <- regWrongOpcFunContract + wrongDataContract <- regWrongDataContract + + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + data: Seq[DataEntry] <- initVOptionDataStackGen(tokenId.arr, tokenId.arr, tokenId.arr, tokenId.arr, ts+100, ts+200) + description <- validDescStringGen + validCreate <- registerVOptionGen(master, validContract, data, description, fee, ts + 1) + wrongOpcCreate <- registerVOptionGen(master, wrongOpcContract, data, description, fee + 10000000000L, ts+2) + wrongDataCreate <- registerVOptionGen(master, wrongDataContract, data, description, fee + 10000000000L, ts+3) + } yield (validCreate, wrongOpcCreate, wrongDataCreate) + + property("register contract transaction cannot pass due to wrong opcode"){ + forAll(preconditionsAndRegContractWrongFun) { case (validCreate, wrongOpcCreate, _) => + assertOpcFuncDifferEi(2, None, validCreate) { opcFunDiffEi => + opcFunDiffEi shouldBe an[Right[_, _]] + } + + assertOpcFuncDifferEi(2, None, wrongOpcCreate) { opcFunDiffEi => + opcFunDiffEi shouldBe Left(ContractInvalidOPCData) + } + } + } + + property("register contract transaction cannot pass due to wrong list of parameters"){ + forAll(preconditionsAndRegContractWrongFun) { case (_, _, wrongDataCreate) => + assertOpcFuncDifferEi(2, None, wrongDataCreate) { opcFunDiffEi => + opcFunDiffEi shouldBe Left(ContractDataTypeMismatch) + } + } + } +} From c431e9cc7926b79f68cfd3cf9ac7e058c730135a Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 14 Jan 2021 14:30:15 +0800 Subject: [PATCH 178/391] Add ExecuteVOptionInvalidDiffTest --- .../vsys/blockchain/contract/Contract.scala | 3 +- .../blockchain/contract/ContractGen.scala | 2 +- .../blockchain/contract/ContractVOption.scala | 10 ++-- .../ExecuteVOptionInvalidDiffTest.scala | 49 +++++++++++++++++++ 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index dd475eef0..d76601666 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -151,7 +151,8 @@ object Contract extends ScorexLogging { !(bytes sameElements ContractLock.contract.bytes.arr) && !(bytes sameElements ContractNonFungible.contract.bytes.arr) && !(bytes sameElements ContractPaymentChannel.contract.bytes.arr) && - !(bytes sameElements ContractVSwap.contract.bytes.arr)) { + !(bytes sameElements ContractVSwap.contract.bytes.arr) && + !(bytes sameElements ContractVOption.contract.bytes.arr)) { log.warn(s"Illegal contract ${bytes.mkString(" ")}") false } else if (textualStr.isFailure || diff --git a/src/main/scala/vsys/blockchain/contract/ContractGen.scala b/src/main/scala/vsys/blockchain/contract/ContractGen.scala index 4aee6576e..06b5197d5 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractGen.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractGen.scala @@ -68,7 +68,7 @@ object ContractGen { val basicConvert = Array(11.toByte, 10.toByte) val conditionIf = Array(12.toByte, 1.toByte) - val conditionIfElse = Array(12.toByte, 1.toByte) + val conditionIfElse = Array(12.toByte, 2.toByte) sealed case class StateVar(index: Byte, dataType: Byte) { lazy val arr: Array[Byte] = Array(index, dataType) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index c3ddac15b..571ee5a1e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -69,8 +69,8 @@ object ContractVOption { cdbvSet ++ Array(proofTokenIdStateVar.index, 3.toByte), cdbvSet ++ Array(executeTimeStateVar.index, 4.toByte), cdbvSet ++ Array(executeDeadlineStateVar.index, 5.toByte), - basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), - cdbvSet ++ Array(optionStatusStateVar.index, 5.toByte) + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), + cdbvSet ++ Array(optionStatusStateVar.index, 7.toByte) ) lazy val initTrigger: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initTriggerOpcs) val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) @@ -113,7 +113,7 @@ object ContractVOption { compareBytesEqual ++ Array(2.toByte, 6.toByte, 14.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( - cdbvMapValAdd ++ Array(optionTokenBalanceMap.index, 0.toByte, 1.toByte), + cdbvMapValAdd ++ Array(proofTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), ) ), DataType.OpcBlock).bytes ++ Array(15.toByte), @@ -164,7 +164,7 @@ object ContractVOption { compareBytesEqual ++ Array(2.toByte, 6.toByte, 14.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( - cdbvMapValMinus ++ Array(optionTokenBalanceMap.index, 0.toByte, 1.toByte), + cdbvMapValMinus ++ Array(proofTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), ) ), DataType.OpcBlock).bytes ++ Array(15.toByte), @@ -220,7 +220,7 @@ object ContractVOption { cdbvStateValAdd ++ Array(reservedProofStateVar.index, 0.toByte), cdbvSet ++ Array(priceStateVar.index, 1.toByte), cdbvSet ++ Array(priceUnitStateVar.index, 2.toByte), - basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(12.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(12.toByte), cdbvSet ++ Array(optionStatusStateVar.index, 12.toByte) ) lazy val activateFunc: Array[Byte] = getFunctionBytes(activateId, publicFuncType, nonReturnType, activateDataType, activateOpcs) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala new file mode 100644 index 000000000..1cc88080c --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -0,0 +1,49 @@ +package test.scala.vsys.blockchain.state.contract.voption + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} +import vsys.blockchain.contract.voption.{VOptionContractGen, VOptionFunctionHelperGen} +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction => EC, RegisterContractTransaction => RC} +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.state._ + +class ExecuteVOptionInvalidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with TokenContractGen + with SystemContractGen + with VOptionContractGen + with VOptionFunctionHelperGen { + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndVOptionDepositAndWithdrawBaseTargetTokens: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, EC, EC, EC, EC)] = for { + (genesis, genesis2, master, _, regBaseTokenContract, _, _, _, regVOptionContract, + issueBaseToken, _, _, _, depositBaseToken, _, _, _, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000L, 1L, 1000L, 1000L, 1L, 1000L, + 100L, 1L, 100L, 1L, 100L, 100L, 1000L, 1000L) + withdrawBaseToken <- withdrawToken(master, regBaseTokenContract.contractId, regVOptionContract.contractId.bytes.arr, master.toAddress.bytes.arr, 100L, fee, ts + 13) + withdrawInvalidBaseToken <- withdrawToken(master, regBaseTokenContract.contractId, regVOptionContract.contractId.bytes.arr, master.toAddress.bytes.arr, 2000L, fee, ts + 13) + } yield (genesis, genesis2, regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken, withdrawBaseToken, withdrawInvalidBaseToken) + + // withdraw base tokens + property("withdraw base tokens more than depositing in voption contract") { + forAll(preconditionsAndVOptionDepositAndWithdrawBaseTargetTokens) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, + depositBaseToken: EC, withdrawBaseToken: EC, withdrawInvalidBaseToken: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken))), + TestBlock.createWithTxStatus(withdrawBaseToken.timestamp, Seq(withdrawBaseToken), TransactionStatus.Success)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositBaseToken.timestamp, Seq(regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken))), + TestBlock.createWithTxStatus(withdrawInvalidBaseToken.timestamp, Seq(withdrawInvalidBaseToken), TransactionStatus.ContractTokenBalanceInsufficient)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient + } + } + } +} \ No newline at end of file From cf64d049e8e3f2488ed474f39fe9b3b7836ae3e8 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Thu, 14 Jan 2021 15:18:21 +0800 Subject: [PATCH 179/391] add unit test for registering v option contract --- .../RegisterVOptionContractDiffTest.scala | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/voption/RegisterVOptionContractDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/RegisterVOptionContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/RegisterVOptionContractDiffTest.scala new file mode 100644 index 000000000..6596e0240 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/voption/RegisterVOptionContractDiffTest.scala @@ -0,0 +1,78 @@ +package vsys.blockchain.state.contract.voption + +import cats.Monoid +import com.google.common.primitives.{Bytes, Ints} +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.{Contract, ContractGenHelper, ContractVOption, DataEntry, DataType} +import vsys.blockchain.contract.voption.VOptionContractGen +import vsys.blockchain.state.diffs.assertDiffAndState +import vsys.blockchain.state._ +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen} +import vsys.blockchain.transaction.contract.RegisterContractTransaction + +class RegisterVOptionContractDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with VOptionContractGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val languageCode: String = "vdds" + val languageVersion: Int = 2 + + val preconditionAndBuildVOptionContract: Gen[(Array[Byte], Array[Byte], Seq[Array[Byte]], + Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]])] = for { + langCode <- ContractGenHelper.languageCodeGen(languageCode) + langVer <- ContractGenHelper.languageVersionGen(languageVersion) + init <- Gen.const(ContractVOption.contract.trigger) + descriptor <- Gen.const(ContractVOption.contract.descriptor) + stateVar <- Gen.const(ContractVOption.contract.stateVar) + stateMap <- Gen.const(ContractVOption.contract.stateMap) + textual <- Gen.const(ContractVOption.contract.textual) + } yield (langCode, langVer, init, descriptor, stateVar, stateMap, textual) + + property("register v-option contract build doesn't break invariant"){ + forAll(preconditionAndBuildVOptionContract) { case (langCode, langVer, init, descriptor, stateVar, stateMap, textual) => + Contract.buildContract(langCode, langVer, init, descriptor, stateVar, stateMap, textual) shouldBe an[Right[_, _]] + } + } + + val validContract: Gen[Contract] = vOptionContractGen() + val preconditionsAndRegContractTest: Gen[(GenesisTransaction, RegisterContractTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + genesis <- genesisVOptionGen(master, ts) + contract <- validContract + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + data: Seq[DataEntry] <- initVOptionDataStackGen(tokenId.arr, tokenId.arr, tokenId.arr, tokenId.arr, ts + 10,ts + 1000) + description <- validDescStringGen + create <- registerVOptionGen(master, contract, data, description, fee, ts + 1) + } yield (genesis, create) + + // Simply registers the v option contract using the system contract token id as inputs + property("register v-option contract transaction doesn't break invariant") { + forAll(preconditionsAndRegContractTest) { case (genesis, reg: RegisterContractTransaction) => + assertDiffAndState(Seq(TestBlock.create(Seq(genesis))), TestBlock.create(Seq(reg))) { (blockDiff, newState) => + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -reg.transactionFee + totalPortfolioDiff.effectiveBalance shouldBe -reg.transactionFee + val master = reg.proofs.firstCurveProof.explicitGet().publicKey + val contractId = reg.contractId.bytes + val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) + + val (_, masterTxs) = newState.accountTransactionIds(master, 2, 0) + masterTxs.size shouldBe 2 // genesis, reg + newState.contractTokens(contractId) shouldBe 0 + newState.contractContent(contractId) shouldEqual Some((2, reg.id, ContractVOption.contract)) + + newState.contractInfo(makerKey) shouldEqual Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + } + } + } +} \ No newline at end of file From 0d8efec02318ca315db32bcbce613d56e156f405 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 14 Jan 2021 15:21:16 +0800 Subject: [PATCH 180/391] add swap base to target func --- .../contract/ContractVStableSwap.scala | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 898b70ffe..d34777625 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -269,6 +269,55 @@ object ContractVStableSwap { ) lazy val closeFunc: Array[Byte] = getFunctionBytes(closeId, publicFuncType, nonReturnType, closeDataType, closeOpcs) val closeTextualBytes: Array[Byte] = textualFunc("close", Seq(), closePara) + + // Swap + val swapBaseToTargetId: Short = 6 + val swapBaseToTargetPara: Seq[String] = Seq("orderId", "amount", "fee", "price", "deadline") ++ + Seq("caller", "status", "lastBlockTime", "isValidTime", "feeInOrder", "priceInOrder", + "minAmount", "isGreaterThanMin", "maxAmount", "isLessThanMax", + "bigIntType", "unitPrice", "unitBigInt", "amountBigInt", "priceBigInt", + "mul", "amountWithoutFeeBigInt", "amountType", "amountWithoutFee", "swapAmount", + "amountZero", "isValidSwapAmount") + val swapBaseToTargetDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) ++ + Array.fill[Byte](3)(DataType.Amount.id.toByte) ++ + Array(DataType.Timestamp.id.toByte) + val swapBaseToTargetOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(5.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 6.toByte), + assertTrue ++ Array(6.toByte), + loadTimestamp ++ Array(7.toByte), + compareGreaterEqual ++ Array(4.toByte, 7.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + cdbvrMapGet ++ Array(feeBaseMap.index, 0.toByte, 9.toByte), + assertEqual ++ Array(2.toByte, 9.toByte), + cdbvrMapGet ++ Array(priceBaseMap.index, 0.toByte, 10.toByte), + assertEqual ++ Array(3.toByte, 10.toByte), + cdbvrMapGet ++ Array(minBaseMap.index, 0.toByte, 11.toByte), + compareGreaterEqual ++ Array(1.toByte, 11.toByte, 12.toByte), + assertTrue ++ Array(12.toByte), + cdbvrMapGet ++ Array(maxBaseMap.index, 0.toByte, 13.toByte), + compareLessEqual ++ Array(1.toByte, 13.toByte, 14.toByte), + assertTrue ++ Array(14.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(15.toByte), + cdbvrGet ++ Array(unitPriceBaseStateVar.index, 16.toByte), + basicConvert ++ Array(16.toByte, 15.toByte, 17.toByte), + basicConvert ++ Array(1.toByte, 15.toByte, 18.toByte), + basicConvert ++ Array(3.toByte, 15.toByte, 19.toByte), + basicMultiply ++ Array(18.toByte, 19.toByte, 20.toByte), + basicDivide ++ Array(20.toByte, 17.toByte, 21.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(22.toByte), + basicConvert ++ Array(21.toByte, 22.toByte, 23.toByte), + basicMinus ++ Array(23.toByte, 2.toByte, 24.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(25.toByte), + compareGreater ++ Array(24.toByte, 25.toByte, 26.toByte), + assertTrue ++ Array(26.toByte), + cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 5.toByte, 1.toByte), + cdbvMapValMinus ++ Array(targetTokenLockedMap.index, 0.toByte, 24.toByte), + cdbvMapValAdd ++ Array(baseTokenLockedMap.index, 0.toByte, 1.toByte), + cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 5.toByte, 24.toByte) + ) + lazy val swapBaseToTargetFunc: Array[Byte] = getFunctionBytes(swapBaseToTargetId, publicFuncType, nonReturnType, swapBaseToTargetDataType, swapBaseToTargetOpcs) + val swapBaseToTargetTextualBytes: Array[Byte] = textualFunc("swapBaseToTarget", Seq(), swapBaseToTargetPara) // Textual } \ No newline at end of file From bfa50b661dd4b477b7829edf424c21f10c0ca5b8 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 14 Jan 2021 15:36:44 +0800 Subject: [PATCH 181/391] add swap common --- .../contract/ContractVStableSwap.scala | 87 ++++++++++--------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index d34777625..c692988c4 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -270,54 +270,59 @@ object ContractVStableSwap { lazy val closeFunc: Array[Byte] = getFunctionBytes(closeId, publicFuncType, nonReturnType, closeDataType, closeOpcs) val closeTextualBytes: Array[Byte] = textualFunc("close", Seq(), closePara) + // Swap Common + val swapCommonPara: Seq[String] = Seq("orderId", "amount", "fee", "price", "deadline") ++ + Seq("caller", "status", "lastBlockTime", "isValidTime", "feeInOrder", "priceInOrder", + "minAmount", "isGreaterThanMin", "maxAmount", "isLessThanMax", + "bigIntType", "unitPrice", "unitBigInt", "amountBigInt", "priceBigInt", + "mul", "amountWithoutFeeBigInt", "amountType", "amountWithoutFee", "swapAmount", + "amountZero", "isValidSwapAmount") + val swapCommonDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) ++ + Array.fill[Byte](3)(DataType.Amount.id.toByte) ++ + Array(DataType.Timestamp.id.toByte) + private def swapCommonOpcs(feeIndex: Byte, priceIndex: Byte, minValue: Byte, maxValue: Byte, unitPriceIndex: Byte): Seq[Array[Byte]] = { + Seq( + loadCaller ++ Array(5.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 6.toByte), + assertTrue ++ Array(6.toByte), + loadTimestamp ++ Array(7.toByte), + compareGreaterEqual ++ Array(4.toByte, 7.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + cdbvrMapGet ++ Array(feeIndex, 0.toByte, 9.toByte), + assertEqual ++ Array(2.toByte, 9.toByte), + cdbvrMapGet ++ Array(priceIndex, 0.toByte, 10.toByte), + assertEqual ++ Array(3.toByte, 10.toByte), + cdbvrMapGet ++ Array(minValue, 0.toByte, 11.toByte), + compareGreaterEqual ++ Array(1.toByte, 11.toByte, 12.toByte), + assertTrue ++ Array(12.toByte), + cdbvrMapGet ++ Array(maxValue, 0.toByte, 13.toByte), + compareLessEqual ++ Array(1.toByte, 13.toByte, 14.toByte), + assertTrue ++ Array(14.toByte), + basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(15.toByte), + cdbvrGet ++ Array(unitPriceIndex, 16.toByte), + basicConvert ++ Array(16.toByte, 15.toByte, 17.toByte), + basicConvert ++ Array(1.toByte, 15.toByte, 18.toByte), + basicConvert ++ Array(3.toByte, 15.toByte, 19.toByte), + basicMultiply ++ Array(18.toByte, 19.toByte, 20.toByte), + basicDivide ++ Array(20.toByte, 17.toByte, 21.toByte), + basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(22.toByte), + basicConvert ++ Array(21.toByte, 22.toByte, 23.toByte), + basicMinus ++ Array(23.toByte, 2.toByte, 24.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(25.toByte), + compareGreater ++ Array(24.toByte, 25.toByte, 26.toByte), + assertTrue ++ Array(26.toByte)) + } + // Swap val swapBaseToTargetId: Short = 6 - val swapBaseToTargetPara: Seq[String] = Seq("orderId", "amount", "fee", "price", "deadline") ++ - Seq("caller", "status", "lastBlockTime", "isValidTime", "feeInOrder", "priceInOrder", - "minAmount", "isGreaterThanMin", "maxAmount", "isLessThanMax", - "bigIntType", "unitPrice", "unitBigInt", "amountBigInt", "priceBigInt", - "mul", "amountWithoutFeeBigInt", "amountType", "amountWithoutFee", "swapAmount", - "amountZero", "isValidSwapAmount") - val swapBaseToTargetDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) ++ - Array.fill[Byte](3)(DataType.Amount.id.toByte) ++ - Array(DataType.Timestamp.id.toByte) - val swapBaseToTargetOpcs: Seq[Array[Byte]] = Seq( - loadCaller ++ Array(5.toByte), - cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 6.toByte), - assertTrue ++ Array(6.toByte), - loadTimestamp ++ Array(7.toByte), - compareGreaterEqual ++ Array(4.toByte, 7.toByte, 8.toByte), - assertTrue ++ Array(8.toByte), - cdbvrMapGet ++ Array(feeBaseMap.index, 0.toByte, 9.toByte), - assertEqual ++ Array(2.toByte, 9.toByte), - cdbvrMapGet ++ Array(priceBaseMap.index, 0.toByte, 10.toByte), - assertEqual ++ Array(3.toByte, 10.toByte), - cdbvrMapGet ++ Array(minBaseMap.index, 0.toByte, 11.toByte), - compareGreaterEqual ++ Array(1.toByte, 11.toByte, 12.toByte), - assertTrue ++ Array(12.toByte), - cdbvrMapGet ++ Array(maxBaseMap.index, 0.toByte, 13.toByte), - compareLessEqual ++ Array(1.toByte, 13.toByte, 14.toByte), - assertTrue ++ Array(14.toByte), - basicConstantGet ++ DataEntry(Array(DataType.BigInteger.id.toByte), DataType.DataTypeObj).bytes ++ Array(15.toByte), - cdbvrGet ++ Array(unitPriceBaseStateVar.index, 16.toByte), - basicConvert ++ Array(16.toByte, 15.toByte, 17.toByte), - basicConvert ++ Array(1.toByte, 15.toByte, 18.toByte), - basicConvert ++ Array(3.toByte, 15.toByte, 19.toByte), - basicMultiply ++ Array(18.toByte, 19.toByte, 20.toByte), - basicDivide ++ Array(20.toByte, 17.toByte, 21.toByte), - basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(22.toByte), - basicConvert ++ Array(21.toByte, 22.toByte, 23.toByte), - basicMinus ++ Array(23.toByte, 2.toByte, 24.toByte), - basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(25.toByte), - compareGreater ++ Array(24.toByte, 25.toByte, 26.toByte), - assertTrue ++ Array(26.toByte), + val swapBaseToTargetOpcs: Seq[Array[Byte]] = swapCommonOpcs(feeBaseMap.index, priceBaseMap.index, minBaseMap.index, maxBaseMap.index, unitPriceBaseStateVar.index) ++ Seq( cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 5.toByte, 1.toByte), cdbvMapValMinus ++ Array(targetTokenLockedMap.index, 0.toByte, 24.toByte), cdbvMapValAdd ++ Array(baseTokenLockedMap.index, 0.toByte, 1.toByte), cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 5.toByte, 24.toByte) ) - lazy val swapBaseToTargetFunc: Array[Byte] = getFunctionBytes(swapBaseToTargetId, publicFuncType, nonReturnType, swapBaseToTargetDataType, swapBaseToTargetOpcs) - val swapBaseToTargetTextualBytes: Array[Byte] = textualFunc("swapBaseToTarget", Seq(), swapBaseToTargetPara) + lazy val swapBaseToTargetFunc: Array[Byte] = getFunctionBytes(swapBaseToTargetId, publicFuncType, nonReturnType, swapCommonDataType, swapBaseToTargetOpcs) + val swapBaseToTargetTextualBytes: Array[Byte] = textualFunc("swapBaseToTarget", Seq(), swapCommonPara) // Textual } \ No newline at end of file From 40754c6facd842632d971d572d87c66eadc3b722 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Thu, 14 Jan 2021 16:22:06 +0800 Subject: [PATCH 182/391] add unit test for depositing tokens into v option contract --- .../voption/ExecuteVOptionValidDiffTest.scala | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala new file mode 100644 index 000000000..97c0cf87c --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala @@ -0,0 +1,80 @@ + +package vsys.blockchain.state.contract.voption + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.token.SystemContractGen +import vsys.blockchain.contract.voption.{VOptionContractGen, VOptionFunctionHelperGen} +import vsys.blockchain.state._ +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.contract.{RegisterContractTransaction => RC, ExecuteContractFunctionTransaction => EC} +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} + +class ExecuteVOptionValidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with SystemContractGen + with VOptionContractGen + with VOptionFunctionHelperGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndVOptionDepositBaseToken: Gen[(GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC, EC)] = for { + // Generates 4 register token contract transactions and a register contract tx for V Option + // Also generates 4 deposit functions, proof and option token deposits the entire supply, deposit amount for base and target tokens can be selected + (genesis, genesis2, master, user, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken , depositProofToken, fee, ts, attach) <- + createBaseTargetOptionProofTokenAndInitVOption( + 1000L, // baseTotalSupply + 1L, // baseUnity + 1000L, // baseIssueAmount + 1000L, // targetTotalSupply + 1L, // targetUnity + 1000L, // targetIssueAmount + 1000L, // optionTotalSupply + 1L, // optionUnity + 1000L, // proofTotalSupply + 1L, // proofUnity + 100L, // baseTokenDepositAmount + 500L, // targetTokenDepositAmount + 1000L, // optionTokenDepositAmount + 1000L) // targetTokenDepositAmount + + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, + issueTargetToken, depositBaseToken, depositTargetToken) + + property("vOption able to deposit") { + forAll(preconditionsAndVOptionDepositBaseToken) { case (genesis: GenesisTransaction, registerBase: RC, + registerTarget: RC, registerOption: RC, registerProof: RC, + registerVOption: RC, issueBase: EC, issueTarget: EC, + depositBase: EC, depositTarget: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, issueTarget, + depositBase))), + TestBlock.createWithTxStatus(depositTarget.timestamp, Seq(depositTarget), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = registerVOption.proofs.firstCurveProof.explicitGet().publicKey + + val (contractBaseTokenBalanceKey, contractTargetTokenBalanceKey, _, _) = getOptionContractTokenBalanceKeys(registerBase.contractId.bytes.arr, + registerTarget.contractId.bytes.arr, registerOption.contractId.bytes.arr, + registerProof.contractId.bytes.arr, registerVOption.contractId.bytes.arr) + + val (masterBaseTokenBalanceKey, masterTargetTokenBalanceKey, _, _) = getOptionUserTokenBalanceKeys(registerBase.contractId.bytes.arr, + registerTarget.contractId.bytes.arr, registerOption.contractId.bytes.arr, + registerProof.contractId.bytes.arr, master) + + newState.tokenAccountBalance(masterBaseTokenBalanceKey) shouldBe 900L // issue 1000, deposit 100 into contract + newState.tokenAccountBalance(contractBaseTokenBalanceKey) shouldBe 100L // deposit 100 into contract + + newState.tokenAccountBalance(masterTargetTokenBalanceKey) shouldBe 500L // issue 1000, deposit 500 into contract + newState.tokenAccountBalance(contractTargetTokenBalanceKey) shouldBe 500L // deposit 500 into contract + } + } + } +} From 74da730c5af1abf9c31aa666e93bcfc7c5325921 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Thu, 14 Jan 2021 16:41:40 +0800 Subject: [PATCH 183/391] add unit test for withdrawing tokens from v option contract --- .../voption/ExecuteVOptionValidDiffTest.scala | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala index 97c0cf87c..80c9875b9 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala @@ -77,4 +77,58 @@ class ExecuteVOptionValidDiffTest extends PropSpec } } } + + // test if we can deposit and withdraw all tokens to and from a v option contract + // all 4 tokens deposit and withdraw has been tested locally, the unit test will test for withdrawing base token only + + val preconditionsAndVoptionWithdrawBaseToken: Gen[(GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, _, _, _, depositBaseToken, _, _ , _, fee, ts, _) <- + createBaseTargetOptionProofTokenAndInitVOption( + 1000L, // baseTotalSupply + 1L, // baseUnity + 1000L, // baseIssueAmount + 1000L, // targetTotalSupply + 1L, // targetUnity + 1000L, // targetIssueAmount + 1000L, // optionTotalSupply + 1L, // optionUnity + 1000L, // proofTotalSupply + 1L, // proofUnity + 1000L, // baseTokenDepositAmount + 1000L, // targetTokenDepositAmount + 1000L, // optionTokenDepositAmount + 1000L) // proofTokenDepositAmount + + withdrawBaseToken <- withdrawToken(master, regBaseTokenContract.contractId, regVOptionContract.contractId.bytes.arr, master.toAddress.bytes.arr, 100L, fee, ts + 13) + + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, depositBaseToken, + withdrawBaseToken) + + property("vOption able to withdraw") { + forAll(preconditionsAndVoptionWithdrawBaseToken) { case (genesis: GenesisTransaction, registerBase: RC, + registerTarget: RC, registerOption: RC, registerProof: RC, + registerVOption: RC, issueBase: EC, depositBase: EC, + withdrawBase: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, depositBase))), + TestBlock.createWithTxStatus(withdrawBase.timestamp, Seq(withdrawBase), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = registerVOption.proofs.firstCurveProof.explicitGet().publicKey + + val (contractBaseTokenBalanceKey, _, _, _) = getOptionContractTokenBalanceKeys(registerBase.contractId.bytes.arr, + registerTarget.contractId.bytes.arr, registerOption.contractId.bytes.arr, + registerProof.contractId.bytes.arr, registerVOption.contractId.bytes.arr) + + val (masterBaseTokenBalanceKey, _, _, _) = getOptionUserTokenBalanceKeys(registerBase.contractId.bytes.arr, + registerTarget.contractId.bytes.arr, registerOption.contractId.bytes.arr, + registerProof.contractId.bytes.arr, master) + + newState.tokenAccountBalance(masterBaseTokenBalanceKey) shouldBe 100L // withdraw 100 + newState.tokenAccountBalance(contractBaseTokenBalanceKey) shouldBe 900L // deposit 1000, withdraw 100 + } + } + } } From cb6ad1ae3c7cbce70d39d22afd418cd336a7d301 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Thu, 14 Jan 2021 17:33:05 +0800 Subject: [PATCH 184/391] add unit test for supersede and activating the v option contract --- .../voption/ExecuteVOptionValidDiffTest.scala | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala index 80c9875b9..2b9328f8b 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala @@ -1,10 +1,14 @@ package vsys.blockchain.state.contract.voption +import com.google.common.primitives.{Ints, Longs} import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.ContractGenHelper.basicContractTestGen +import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.token.SystemContractGen import vsys.blockchain.contract.voption.{VOptionContractGen, VOptionFunctionHelperGen} import vsys.blockchain.state._ @@ -131,4 +135,92 @@ class ExecuteVOptionValidDiffTest extends PropSpec } } } + + // testing logic of supersede, address registering the v option contract and activating it should be different + // making the user address register and issue tokens reduces need for sending over tokens before activating + + val preconditionsAndVOptionSupersedeActivate: Gen[(GenesisTransaction, GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + + (master, ts, fee) <- basicContractTestGen() + + genesis <- genesisVOptionGen(master, ts) + user <- accountGen + genesis2 <- genesisVOptionGen(user, ts) + vOptionContract <- vOptionContractGen() + + // register base token + regBaseTokenContract <- registerToken(user, 1000L, 1L, "init", fee + 10000000000L, ts) + baseTokenContractId = regBaseTokenContract.contractId + baseTokenId = tokenIdFromBytes(baseTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register target token + regTargetTokenContract <- registerToken(user, 1000L, 1L, "init", fee + 10000000000L, ts + 1) + targetTokenContractId = regTargetTokenContract.contractId + targetTokenId = tokenIdFromBytes(targetTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register option token + regOptionTokenContract <- registerToken(user, 1000L, 1L, "init", fee + 10000000000L, ts + 2) + optionTokenContractId = regOptionTokenContract.contractId + optionTokenId = tokenIdFromBytes(optionTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // register proof token + regProofTokenContract <- registerToken(user, 1000L, 1L, "init", fee + 10000000000L, ts + 3) + proofTokenContractId = regProofTokenContract.contractId + proofTokenId = tokenIdFromBytes(proofTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + // register VSwap contract + description <- validDescStringGen + initVOptionDataStack: Seq[DataEntry] <- initVOptionDataStackGen(baseTokenId.arr, targetTokenId.arr, optionTokenId.arr, proofTokenId.arr, ts + 100, ts + 200) + regVOptionContract <- registerVOptionGen(master, vOptionContract, initVOptionDataStack, description, fee + 10000000000L, ts + 4) + vOptionContractId = regVOptionContract.contractId + + // issue base token + attach <- genBoundedString(2, EC.MaxDescriptionSize) + issueBaseToken <- issueToken(user, baseTokenContractId, 1000L, fee, ts + 5) + // issue target token + issueTargetToken <- issueToken(user, targetTokenContractId, 1000L, fee, ts + 6) + // issue option token, issue the entire supply of option tokens + issueOptionToken <- issueToken(user, optionTokenContractId, 1000L, fee, ts + 7) + // issue proof token, issue the entire supply of proof tokens + issueProofToken <- issueToken(user, proofTokenContractId, 1000L, fee, ts + 8) + + depositBaseToken <- depositToken(user, baseTokenContractId, user.toAddress.bytes.arr, vOptionContractId.bytes.arr, 1000L, fee + 10000000000L, ts + 9) + depositTargetToken <- depositToken(user, targetTokenContractId, user.toAddress.bytes.arr, vOptionContractId.bytes.arr, 1000L, fee + 10000000000L, ts + 10) + depositOptionToken <- depositToken(user, optionTokenContractId, user.toAddress.bytes.arr, vOptionContractId.bytes.arr, 1000L, fee + 10000000000L, ts + 11) + depositProofToken <- depositToken(user, proofTokenContractId, user.toAddress.bytes.arr, vOptionContractId.bytes.arr, 1000L, fee + 10000000000L, ts + 12) + + supersedeOption <- supersedeVOptionGen(master, regVOptionContract.contractId, user.toAddress, attach, fee, ts + 13) + activateOption <- activateVOptionGen(user, regVOptionContract.contractId, 1000L, 10L, 10L, attach, fee, ts + 14) + } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, + issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, supersedeOption, activateOption) + + property("vOption able to supersede and activate") { + forAll(preconditionsAndVOptionSupersedeActivate) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, registerBase: RC, registerTarget: RC, + registerOption: RC, registerProof: RC, registerVOption: RC, issueBase: EC, + issueTarget: EC, issueOption: EC, issueProof: EC, depositBase: EC, + depositTarget: EC, depositOption: EC, depositProof: EC, + supersede: EC, activate: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, issueTarget, + issueOption, issueProof, depositBase, depositTarget, depositOption, depositProof))), + TestBlock.createWithTxStatus(activate.timestamp, Seq(supersede, activate), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val user = registerBase.proofs.firstCurveProof.explicitGet().publicKey + val vOptionContractId = registerVOption.contractId.bytes.arr + + val (optionStatusKey, maxIssueNumKey, reservedOptionKey, + reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) = getOptionContractStateVarKeys(vOptionContractId) + + val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, + userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) + newState.contractNumInfo(reservedOptionKey) shouldBe 1000L + newState.contractNumInfo(reservedProofKey) shouldBe 1000L + newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractNumInfo(tokenLockedKey) shouldBe 0L + } + } + } } From 46b649a00221a7dbca1bb91f1af96d94249e49e1 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Thu, 14 Jan 2021 18:06:27 +0800 Subject: [PATCH 185/391] add unit test for mint, unlock and executing the v options contract --- .../voption/ExecuteVOptionValidDiffTest.scala | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala index 2b9328f8b..768450035 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala @@ -223,4 +223,179 @@ class ExecuteVOptionValidDiffTest extends PropSpec } } } + + val preconditionsAndVOptionMint: Gen[(GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, + EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- + createBaseTargetOptionProofTokenAndInitVOption( + 1000L, // baseTotalSupply + 1L, // baseUnity + 1000L, // baseIssueAmount + 1000L, // targetTotalSupply + 1L, // targetUnity + 1000L, // targetIssueAmount + 1000L, // optionTotalSupply + 1L, // optionUnity + 1000L, // proofTotalSupply + 1L, // proofUnity + 1000L, // baseTokenDepositAmount + 1000L, // targetTokenDepositAmount + 1000L, // optionTokenDepositAmount + 1000L) // proofTokenDepositAmount + + activateOption <- activateVOptionGen(master, regVOptionContract.contractId, 1000L, 10L, 10L, attach, fee, ts + 13) + mintOption <- mintVOptionGen(master, regVOptionContract.contractId, 500L, attach, fee, ts + 14) + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, + issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activateOption, mintOption) + + property("vOption able to mint") { + forAll(preconditionsAndVOptionMint) { case (genesis: GenesisTransaction, registerBase: RC, registerTarget: RC, + registerOption: RC, registerProof: RC, registerVOption: RC, issueBase: EC, + issueTarget: EC, issueOption: EC, issueProof: EC, depositBase: EC, + depositTarget: EC, depositOption: EC, depositProof: EC, activate: EC, + mint: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, issueTarget, + issueOption, issueProof, depositBase, depositTarget, depositOption, depositProof, activate))), + TestBlock.createWithTxStatus(mint.timestamp, Seq(mint), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val user = registerBase.proofs.firstCurveProof.explicitGet().publicKey + val vOptionContractId = registerVOption.contractId.bytes.arr + + val (optionStatusKey, maxIssueNumKey, reservedOptionKey, + reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) = getOptionContractStateVarKeys(vOptionContractId) + + val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, + userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) + newState.contractNumInfo(reservedOptionKey) shouldBe 500L + newState.contractNumInfo(reservedProofKey) shouldBe 500L + newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractNumInfo(tokenLockedKey) shouldBe 500L + + } + } + } + + val preconditionsAndVOptionUnlock: Gen[(GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- + createBaseTargetOptionProofTokenAndInitVOption( + 1000L, // baseTotalSupply + 1L, // baseUnity + 1000L, // baseIssueAmount + 1000L, // targetTotalSupply + 1L, // targetUnity + 1000L, // targetIssueAmount + 1000L, // optionTotalSupply + 1L, // optionUnity + 1000L, // proofTotalSupply + 1L, // proofUnity + 1000L, // baseTokenDepositAmount + 1000L, // targetTokenDepositAmount + 1000L, // optionTokenDepositAmount + 1000L) // proofTokenDepositAmount + + activateOption <- activateVOptionGen(master, regVOptionContract.contractId, 1000L, 10L, 10L, attach, fee, ts + 13) + mintOption <- mintVOptionGen(master, regVOptionContract.contractId, 10L, attach, fee, ts + 14) + unlockOption <- unlockVOptionGen(master, regVOptionContract.contractId, 10L, attach, fee, ts + 15) + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, + issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activateOption, mintOption, unlockOption) + + property("vOption able to unlock") { + forAll(preconditionsAndVOptionUnlock) { case (genesis: GenesisTransaction, registerBase: RC, registerTarget: RC, + registerOption: RC, registerProof: RC, registerVOption: RC, issueBase: EC, + issueTarget: EC, issueOption: EC, issueProof: EC, depositBase: EC, + depositTarget: EC, depositOption: EC, depositProof: EC, activate: EC, + mint: EC, unlock: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, issueTarget, + issueOption, issueProof, depositBase, depositTarget, depositOption, depositProof, activate, mint))), + TestBlock.createWithTxStatus(unlock.timestamp, Seq(unlock), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val user = registerBase.proofs.firstCurveProof.explicitGet().publicKey + val vOptionContractId = registerVOption.contractId.bytes.arr + + val (optionStatusKey, maxIssueNumKey, reservedOptionKey, + reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) = getOptionContractStateVarKeys(vOptionContractId) + + val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, + userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) + newState.contractNumInfo(reservedOptionKey) shouldBe 1000L + newState.contractNumInfo(reservedProofKey) shouldBe 1000L + newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractNumInfo(tokenLockedKey) shouldBe 0L + } + } + } + + val preconditionsAndVOptionExecute: Gen[(GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- + createBaseTargetOptionProofTokenAndInitVOption( + 1000L, // baseTotalSupply + 1L, // baseUnity + 1000L, // baseIssueAmount + 1000L, // targetTotalSupply + 1L, // targetUnity + 1000L, // targetIssueAmount + 1000L, // optionTotalSupply + 1L, // optionUnity + 1000L, // proofTotalSupply + 1L, // proofUnity + 1000L, // baseTokenDepositAmount + 1000L, // targetTokenDepositAmount + 1000L, // optionTokenDepositAmount + 1000L) // proofTokenDepositAmount + + activateOption <- activateVOptionGen(master, regVOptionContract.contractId, 1000L, 10L, 1L, attach, fee, ts + 13) + mintOption <- mintVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee, ts + 14) + executeOption <- executeVOptionGen(master, regVOptionContract.contractId, 10L, attach, fee, ts + 101) + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, + issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activateOption, mintOption, executeOption) + + property("vOption able to execute") { + forAll(preconditionsAndVOptionExecute) { case (genesis: GenesisTransaction, registerBase: RC, registerTarget: RC, + registerOption: RC, registerProof: RC, registerVOption: RC, issueBase: EC, + issueTarget: EC, issueOption: EC, issueProof: EC, depositBase: EC, + depositTarget: EC, depositOption: EC, depositProof: EC, activate: EC, + mint: EC, execute: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, issueTarget, + issueOption, issueProof, depositBase, depositTarget, depositOption, depositProof, activate, mint))), + TestBlock.createWithTxStatus(execute.timestamp, Seq(execute), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val user = registerBase.proofs.firstCurveProof.explicitGet().publicKey + val vOptionContractId = registerVOption.contractId.bytes.arr + + val (optionStatusKey, maxIssueNumKey, reservedOptionKey, + reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) = getOptionContractStateVarKeys(vOptionContractId) + + val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, + userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) + newState.contractNumInfo(reservedOptionKey) shouldBe 910L + newState.contractNumInfo(reservedProofKey) shouldBe 900L + newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(tokenLockedKey) shouldBe 90L + } + } + } } From 88ac2b71e89be1c253e26b589a452db075423d2a Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 15 Jan 2021 10:51:03 +0800 Subject: [PATCH 186/391] add swap target to base func --- .../vsys/blockchain/contract/ContractVStableSwap.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index c692988c4..c90c61c6a 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -323,6 +323,16 @@ object ContractVStableSwap { ) lazy val swapBaseToTargetFunc: Array[Byte] = getFunctionBytes(swapBaseToTargetId, publicFuncType, nonReturnType, swapCommonDataType, swapBaseToTargetOpcs) val swapBaseToTargetTextualBytes: Array[Byte] = textualFunc("swapBaseToTarget", Seq(), swapCommonPara) + + val swapTargetToBaseId: Short = 7 + val swapTargetToBaseOpcs: Seq[Array[Byte]] = swapCommonOpcs(feeTargetMap.index, priceTargetMap.index, minTargetMap.index, maxTargetMap.index, unitPriceTargetStateVar.index) ++ Seq( + cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 5.toByte, 1.toByte), + cdbvMapValMinus ++ Array(baseTokenLockedMap.index, 0.toByte, 24.toByte), + cdbvMapValAdd ++ Array(targetTokenLockedMap.index, 0.toByte, 1.toByte), + cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 5.toByte, 24.toByte) + ) + lazy val swapTargetToBaseFunc: Array[Byte] = getFunctionBytes(swapTargetToBaseId, publicFuncType, nonReturnType, swapCommonDataType, swapTargetToBaseOpcs) + val swapTargetToBaseTextualBytes: Array[Byte] = textualFunc("swapTargetToBase", Seq(), swapCommonPara) // Textual } \ No newline at end of file From 80c0b6b1df6df1d0c9a4a3e42d2a14fbbfe41635 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 15 Jan 2021 10:57:53 +0800 Subject: [PATCH 187/391] update textual and complete the contract --- .../blockchain/contract/ContractVStableSwap.scala | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index c90c61c6a..cc728fe43 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -8,10 +8,11 @@ import vsys.utils.serialization.Deser object ContractVStableSwap { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), Seq(initTrigger, depositTrigger, withdrawTrigger), // Triggers - Seq(), // Functions + Seq(supersedeFunc, setOrderFunc, updateFunc, orderDepositFunc, orderWithdrawFunc, closeFunc, + swapBaseToTargetFunc, swapTargetToBaseFunc), // Functions stateVarSeq, // StateVars stateMapSeq, // StateMaps - Seq() // Textual + Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual) // Textual ).explicitGet() // State Var @@ -234,7 +235,7 @@ object ContractVStableSwap { cdbvMapValAdd ++ Array(targetTokenLockedMap.index, 0.toByte, 2.toByte) ) lazy val orderDepositFunc: Array[Byte] = getFunctionBytes(orderDepositId, publicFuncType, nonReturnType, orderDepositDataType, orderDepositOpcs) - val OrderDepositTextualBytes: Array[Byte] = textualFunc("orderDeposit", Seq(), orderDepositPara) + val orderDepositTextualBytes: Array[Byte] = textualFunc("orderDeposit", Seq(), orderDepositPara) // Order Withdraw val orderWithdrawId: Short = 4 @@ -333,6 +334,11 @@ object ContractVStableSwap { ) lazy val swapTargetToBaseFunc: Array[Byte] = getFunctionBytes(swapTargetToBaseId, publicFuncType, nonReturnType, swapCommonDataType, swapTargetToBaseOpcs) val swapTargetToBaseTextualBytes: Array[Byte] = textualFunc("swapTargetToBase", Seq(), swapCommonPara) + // Textual + lazy val triggerTextual: Array[Byte] = Deser.serializeArrays(Seq(initTextualBytes, depositTextualBytes, withdrawTextualBytes)) + lazy val descriptorTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeTextualBytes, setOrderTextualBytes, updateTextualBytes, + orderDepositTextualBytes, orderWithdrawTextualBytes, closeTextualBytes, swapBaseToTargetTextualBytes, swapTargetToBaseTextualBytes)) + } \ No newline at end of file From 511ef9aae5553b64630d1e71291f9f8e43be252a Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Fri, 15 Jan 2021 11:41:29 +0800 Subject: [PATCH 188/391] add test case for collect function of v option contract and add clarifying comments --- .../voption/ExecuteVOptionValidDiffTest.scala | 83 ++++++++++++++++--- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala index 768450035..90db37668 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala @@ -273,11 +273,11 @@ class ExecuteVOptionValidDiffTest extends PropSpec newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) - newState.contractNumInfo(reservedOptionKey) shouldBe 500L - newState.contractNumInfo(reservedProofKey) shouldBe 500L + newState.contractNumInfo(reservedOptionKey) shouldBe 500L // maxIssueNum 1000, mint 500 + newState.contractNumInfo(reservedProofKey) shouldBe 500L // maxIssueNum 1000, mint 500 newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) - newState.contractNumInfo(tokenLockedKey) shouldBe 500L + newState.contractNumInfo(tokenLockedKey) shouldBe 500L // mint 500 } } @@ -304,7 +304,7 @@ class ExecuteVOptionValidDiffTest extends PropSpec 1000L) // proofTokenDepositAmount activateOption <- activateVOptionGen(master, regVOptionContract.contractId, 1000L, 10L, 10L, attach, fee, ts + 13) - mintOption <- mintVOptionGen(master, regVOptionContract.contractId, 10L, attach, fee, ts + 14) + mintOption <- mintVOptionGen(master, regVOptionContract.contractId, 500L, attach, fee, ts + 14) unlockOption <- unlockVOptionGen(master, regVOptionContract.contractId, 10L, attach, fee, ts + 15) } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activateOption, mintOption, unlockOption) @@ -332,11 +332,11 @@ class ExecuteVOptionValidDiffTest extends PropSpec newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) - newState.contractNumInfo(reservedOptionKey) shouldBe 1000L - newState.contractNumInfo(reservedProofKey) shouldBe 1000L + newState.contractNumInfo(reservedOptionKey) shouldBe 510L // maxIssueNum 1000, mint 500, unlock 10 + newState.contractNumInfo(reservedProofKey) shouldBe 510L // maxIssueNum 1000, mint 500, unlock 10 newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) - newState.contractNumInfo(tokenLockedKey) shouldBe 0L + newState.contractNumInfo(tokenLockedKey) shouldBe 490L // mint 500, unlock 10 } } } @@ -390,11 +390,74 @@ class ExecuteVOptionValidDiffTest extends PropSpec newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) - newState.contractNumInfo(reservedOptionKey) shouldBe 910L - newState.contractNumInfo(reservedProofKey) shouldBe 900L + newState.contractNumInfo(reservedOptionKey) shouldBe 910L // maxIssueNum 1000, mint 100, execute 10 + newState.contractNumInfo(reservedProofKey) shouldBe 900L // maxIssueNum 1000, mint 100 + newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(tokenLockedKey) shouldBe 90L // mint 100, execute 10 + } + } + } + + val preconditionsAndVOptionCollect: Gen[(GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- + createBaseTargetOptionProofTokenAndInitVOption( + 1000L, // baseTotalSupply + 1L, // baseUnity + 1000L, // baseIssueAmount + 1000L, // targetTotalSupply + 1L, // targetUnity + 1000L, // targetIssueAmount + 1000L, // optionTotalSupply + 1L, // optionUnity + 1000L, // proofTotalSupply + 1L, // proofUnity + 1000L, // baseTokenDepositAmount + 1000L, // targetTokenDepositAmount + 1000L, // optionTokenDepositAmount + 1000L) // proofTokenDepositAmount + + activateOption <- activateVOptionGen(master, regVOptionContract.contractId, 1000L, 10L, 1L, attach, fee, ts + 13) + mintOption <- mintVOptionGen(master, regVOptionContract.contractId, 500L, attach, fee, ts + 14) + executeOption <- executeVOptionGen(master, regVOptionContract.contractId, 10L, attach, fee, ts + 101) + collectOption <- collectVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee, ts + 202) + + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, + issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activateOption, mintOption, executeOption, collectOption) + + property("vOption able to collect") { + forAll(preconditionsAndVOptionCollect) { case (genesis: GenesisTransaction, registerBase: RC, registerTarget: RC, + registerOption: RC, registerProof: RC, registerVOption: RC, issueBase: EC, + issueTarget: EC, issueOption: EC, issueProof: EC, depositBase: EC, + depositTarget: EC, depositOption: EC, depositProof: EC, activate: EC, + mint: EC, execute: EC, collect: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, issueTarget, + issueOption, issueProof, depositBase, depositTarget, depositOption, depositProof, activate, mint)), TestBlock.create(execute.timestamp, Seq()), // empty block since transactions look at previous block timestamp + TestBlock.create(execute.timestamp + 1, Seq(execute))), + TestBlock.createWithTxStatus(collect.timestamp, Seq(collect), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val user = registerBase.proofs.firstCurveProof.explicitGet().publicKey + val vOptionContractId = registerVOption.contractId.bytes.arr + + val (optionStatusKey, maxIssueNumKey, reservedOptionKey, + reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) = getOptionContractStateVarKeys(vOptionContractId) + + val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, + userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) + newState.contractNumInfo(reservedOptionKey) shouldBe 510L // maxIssueNum 1000, mint 500, execute 10 + newState.contractNumInfo(reservedProofKey) shouldBe 600L // maxIssueNum 1000, mint 500, collect 100 newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) - newState.contractNumInfo(tokenLockedKey) shouldBe 90L + // the collect function gives the caller the fraction of the pool equal to the fraction of proof tokens they use to execute the function + // here there are 490 target tokens and 500 available proof tokens + newState.contractNumInfo(tokenLockedKey) shouldBe 392L // 490 - ((100/500) * 490) } } } From 9fd82d6c24bd5bb30691fbd17a092394c6a50a08 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 14 Jan 2021 16:35:55 +0800 Subject: [PATCH 189/391] Add activate VOptionInvalidDiffTest --- .../ExecuteVOptionInvalidDiffTest.scala | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index 1cc88080c..1c79ddc6a 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -46,4 +46,43 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } } + + val preconditionsAndVOptionActivate: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000, 1, 1000, 1000, 1, 1000, + 1000, 1,1000, 1, 1000, 1000, 1000, 1000) + activate <- activateVOptionGen(master, regVOptionContract.contractId, 1000, 1,1, attach, fee + 10000000000L, ts+13) + activateInvalid <- activateVOptionGen(master, regVOptionContract.contractId, 10000, 1,1, attach, fee + 10000000000L, ts+13) + + } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, activateInvalid) + + property("activate voption more than depositing in voption contract") { + forAll(preconditionsAndVOptionActivate) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, + regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, + issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, activateInvalid: EC) => + + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(activate.timestamp, Seq(activate), TransactionStatus.Success)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(activateInvalid.timestamp, Seq(activateInvalid), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + + + + } \ No newline at end of file From 817a78c82c1016d789b263e6829eb255a627bfc2 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 14 Jan 2021 16:44:01 +0800 Subject: [PATCH 190/391] Add mint VOptionInvalidDiffTest --- .../ExecuteVOptionInvalidDiffTest.scala | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index 1c79ddc6a..ee5cf326f 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -81,6 +81,61 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } + val preconditionsAndVOptionMint: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000, 1, 1000, 1000, 1, 1000, + 100, 1,100, 1, 1000, 1000, 100, 100) + + activate <- activateVOptionGen(master, regVOptionContract.contractId, 100, 1,1, attach, fee + 10000000000L, ts+13) + mint <- mintVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+14) + mintInvalid <- mintVOptionGen(master, regVOptionContract.contractId, 1000, attach, fee + 10000000000L, ts+14) + mintInvalid2 <- mintVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+101) + mintInvalid3 <- mintVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+201) + } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, mintInvalid, mintInvalid2, mintInvalid3) + + property("unable to mint") { + forAll(preconditionsAndVOptionMint) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, + regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, issueOptionToken: EC, + issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, + activate: EC, mint: EC, mintInvalid: EC, mintInvalid2: EC, mintInvalid3: EC) => + + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate))), + TestBlock.createWithTxStatus(mint.timestamp, Seq(mint), TransactionStatus.Success)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // mint voption is greater than maxIssueNum + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate))), + TestBlock.createWithTxStatus(mintInvalid.timestamp, Seq(mintInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // mint after executeTime + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate))), + TestBlock.createWithTxStatus(mintInvalid2.timestamp, Seq(mintInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // mint after executeDeadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate))), + TestBlock.createWithTxStatus(mintInvalid3.timestamp, Seq(mintInvalid3), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } From 2d855a524d4dc1f0f0469f72d85cb0536a7eef22 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Fri, 15 Jan 2021 10:56:53 +0800 Subject: [PATCH 191/391] Add unlock VOptionInvalidDiffTest --- .../ExecuteVOptionInvalidDiffTest.scala | 69 ++++++++++++++++--- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index ee5cf326f..374db5a0a 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -47,21 +47,21 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } - val preconditionsAndVOptionActivate: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { - (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + val preconditionsAndVOptionActivate: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC,EC,EC)] = for { + (genesis, genesis2, master, user, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000, 1, 1000, 1000, 1, 1000, 1000, 1,1000, 1, 1000, 1000, 1000, 1000) activate <- activateVOptionGen(master, regVOptionContract.contractId, 1000, 1,1, attach, fee + 10000000000L, ts+13) activateInvalid <- activateVOptionGen(master, regVOptionContract.contractId, 10000, 1,1, attach, fee + 10000000000L, ts+13) - + activateInvalid2 <- activateVOptionGen(user, regVOptionContract.contractId, 1000, 1,1, attach, fee + 10000000000L, ts+13) } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, - issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, activateInvalid) + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, activateInvalid, activateInvalid2) - property("activate voption more than depositing in voption contract") { + property("unable to activate voption contract") { forAll(preconditionsAndVOptionActivate) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, - issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, activateInvalid: EC) => + issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, activateInvalid: EC, activateInvalid2: EC) => assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, @@ -69,7 +69,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(activate.timestamp, Seq(activate), TransactionStatus.Success)) { (blockDiffEi) => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } - + // activate amount more than depositing in voption contract assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken))), @@ -78,6 +78,15 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed } + // activated by another user + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(activateInvalid2.timestamp, Seq(activateInvalid2), TransactionStatus.ContractInvalidCaller)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } } } @@ -94,7 +103,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, mintInvalid, mintInvalid2, mintInvalid3) - property("unable to mint") { + property("unable to mint voption") { forAll(preconditionsAndVOptionMint) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, issueOptionToken: EC, @@ -137,7 +146,51 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } + val preconditionsAndVOptionUnlock: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000, 1, 1000, 1000, 1, 1000, + 100, 1,100, 1, 1000, 1000, 100, 100) + activate <- activateVOptionGen(master, regVOptionContract.contractId, 100, 1,1, attach, fee + 10000000000L, ts+13) + mint <- mintVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+14) + unlock <- unlockVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+14) + unlockInvalid <- unlockVOptionGen(master, regVOptionContract.contractId, 100, attach, fee + 10000000000L, ts+14) + unlockInvalid2 <- unlockVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+201) + } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, unlock, unlockInvalid, unlockInvalid2) + + property("unable to unlock") { + forAll(preconditionsAndVOptionUnlock) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, + issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, mint: EC, unlock: EC, + unlockInvalid: EC, unlockInvalid2: EC) => + + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint))), + TestBlock.createWithTxStatus(unlock.timestamp, Seq(unlock), TransactionStatus.Success)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // unlock voption greater than mint amount + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint))), + TestBlock.createWithTxStatus(unlockInvalid.timestamp, Seq(unlockInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // unlock voption after executedeadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint))), + TestBlock.createWithTxStatus(unlockInvalid2.timestamp, Seq(unlockInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } } \ No newline at end of file From e24265de9baab158287a1b5013dc7cb5c84c7cc5 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Fri, 15 Jan 2021 14:04:04 +0800 Subject: [PATCH 192/391] Add execute VOptionInvalidDiffTest --- .../ExecuteVOptionInvalidDiffTest.scala | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index 374db5a0a..7854503c3 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -192,5 +192,61 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } + val preconditionsAndVOptionExecute: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000L, 1L, 1000L, 1000L, 1L, 1000L, + 1000L, 1L,1000L, 1L, 1000L, 1000L, 1000, 1000) + + activate <- activateVOptionGen(master, regVOptionContract.contractId, 1000L, 10L,1L, attach, fee + 10000000000L, ts+13) + mint <- mintVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+14) + + execute <- executeVOptionGen(master, regVOptionContract.contractId, 10L, attach, fee + 10000000000L, ts+101) + executeInvalid <- executeVOptionGen(master, regVOptionContract.contractId, 1000L, attach, fee + 10000000000L, ts+101) + executeInvalid2 <- executeVOptionGen(master, regVOptionContract.contractId, 1000L, attach, fee + 10000000000L, ts+99) + executeInvalid3 <- executeVOptionGen(master, regVOptionContract.contractId, 1000L, attach, fee + 10000000000L, ts+201) + } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, execute, executeInvalid, executeInvalid2, executeInvalid3) + + property("unable to execute voption") { + forAll(preconditionsAndVOptionExecute) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, + regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, + depositOptionToken: EC, depositProofToken: EC, activate: EC, mint: EC, execute: EC, executeInvalid: EC, executeInvalid2: EC, executeInvalid3: EC) => + + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint))), + TestBlock.createWithTxStatus(execute.timestamp, Seq(execute), TransactionStatus.Success)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success + } + // execute voption more than target token balance + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint))), + TestBlock.createWithTxStatus(executeInvalid.timestamp, Seq(executeInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // execute voption before execute time + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint))), + TestBlock.createWithTxStatus(executeInvalid2.timestamp, Seq(executeInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // execute voption after execute deadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint))), + TestBlock.createWithTxStatus(executeInvalid3.timestamp, Seq(executeInvalid3), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } } \ No newline at end of file From a925ad82bee1a2b306cb859288f7078401daf1ac Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Fri, 15 Jan 2021 14:21:24 +0800 Subject: [PATCH 193/391] Add collect VOptionInvalidDiffTest --- .../ExecuteVOptionInvalidDiffTest.scala | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index 7854503c3..696574ff7 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -248,5 +248,71 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } } + val preconditionsAndVOptionCollect: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000L, 1L, 1000L, 1000L, 1L, 1000L, + 1000L, 1L,1000L, 1L, 1000L, 1000L, 1000, 1000) + + activate <- activateVOptionGen(master, regVOptionContract.contractId, 1000L, 10L,1L, attach, fee + 10000000000L, ts+13) + mint <- mintVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+14) + execute <- executeVOptionGen(master, regVOptionContract.contractId, 2L, attach, fee + 10000000000L, ts+199) + collect <- collectVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+100000000) + collectInvalid <- collectVOptionGen(master, regVOptionContract.contractId, 1000L, attach, fee + 10000000000L, ts+100000000) + collectInvalid2 <- collectVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+99) + collectInvalid3 <- collectVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+199) + + } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, execute, collect, collectInvalid, collectInvalid2, collectInvalid3) + + property("unable to collect voption") { + forAll(preconditionsAndVOptionCollect) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, + regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, + issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, + activate: EC, mint: EC, execute: EC, collect: EC, collectInvalid: EC, collectInvalid2: EC, collectInvalid3: EC) => + + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint)), + TestBlock.create(execute.timestamp, Seq()), + TestBlock.create(execute.timestamp+1, Seq(execute))), + TestBlock.createWithTxStatus(collect.timestamp, Seq(collect), TransactionStatus.Success)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success + } + // collect voption more than mint amount + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint)), + TestBlock.create(execute.timestamp, Seq()), + TestBlock.create(execute.timestamp+1, Seq(execute))), + TestBlock.createWithTxStatus(collectInvalid.timestamp, Seq(collectInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // collect voption before execute time + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint)), + TestBlock.create(execute.timestamp, Seq()), + TestBlock.create(execute.timestamp+1, Seq(execute))), + TestBlock.createWithTxStatus(collectInvalid2.timestamp, Seq(collectInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // collect voption after execute deadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint)), + TestBlock.create(execute.timestamp, Seq()), + TestBlock.create(execute.timestamp+1, Seq(execute))), + TestBlock.createWithTxStatus(collectInvalid3.timestamp, Seq(collectInvalid3), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } } \ No newline at end of file From 7567727e17e6d15f8dbb4a3bdfb79e54530f4190 Mon Sep 17 00:00:00 2001 From: Tsz Wai Date: Fri, 15 Jan 2021 17:18:38 +0800 Subject: [PATCH 194/391] test V Option execute and collect functions using max Long values --- .../voption/ExecuteVOptionValidDiffTest.scala | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala index 90db37668..4124f8a21 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala @@ -461,4 +461,172 @@ class ExecuteVOptionValidDiffTest extends PropSpec } } } + + val preconditionsAndVOptionLargeAmountsExecute: Gen[(GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- + createBaseTargetOptionProofTokenAndInitVOption( + Long.MaxValue, // baseTotalSupply + 1L, // baseUnity + Long.MaxValue, // baseIssueAmount + Long.MaxValue, // targetTotalSupply + 1L, // targetUnity + Long.MaxValue, // targetIssueAmount + Long.MaxValue, // optionTotalSupply + 1L, // optionUnity + Long.MaxValue, // proofTotalSupply + 1L, // proofUnity + Long.MaxValue, // baseTokenDepositAmount + Long.MaxValue, // targetTokenDepositAmount + Long.MaxValue, // optionTokenDepositAmount + Long.MaxValue) // proofTokenDepositAmount + + activateOption <- activateVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, Long.MaxValue, 1L, attach, fee, ts + 13) + mintOption <- mintVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, attach, fee, ts + 14) + executeOption <- executeVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, attach, fee, ts + 101) + + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, + issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activateOption, mintOption, executeOption) + + property("vOption able to execute very large numbers") { + forAll(preconditionsAndVOptionLargeAmountsExecute) { case (genesis: GenesisTransaction, registerBase: RC, registerTarget: RC, + registerOption: RC, registerProof: RC, registerVOption: RC, issueBase: EC, + issueTarget: EC, issueOption: EC, issueProof: EC, depositBase: EC, + depositTarget: EC, depositOption: EC, depositProof: EC, activate: EC, + mint: EC, execute: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, issueTarget, + issueOption, issueProof, depositBase, depositTarget, depositOption, depositProof, activate, mint))), + TestBlock.createWithTxStatus(execute.timestamp, Seq(execute), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val user = registerBase.proofs.firstCurveProof.explicitGet().publicKey + val vOptionContractId = registerVOption.contractId.bytes.arr + + val (optionStatusKey, maxIssueNumKey, reservedOptionKey, + reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) = getOptionContractStateVarKeys(vOptionContractId) + + val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, + userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) + newState.contractNumInfo(reservedOptionKey) shouldBe Long.MaxValue + newState.contractNumInfo(reservedProofKey) shouldBe 0L + newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) + newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(tokenLockedKey) shouldBe 0L + + val master = registerVOption.proofs.firstCurveProof.explicitGet().publicKey + + val (contractBaseTokenBalanceKey, contractTargetTokenBalanceKey, + contractOptionTokenBalanceKey, contractProofTokenBalanceKey) = getOptionContractTokenBalanceKeys(registerBase.contractId.bytes.arr, + registerTarget.contractId.bytes.arr, registerOption.contractId.bytes.arr, + registerProof.contractId.bytes.arr, registerVOption.contractId.bytes.arr) + + val (masterBaseTokenBalanceKey, masterTargetTokenBalanceKey, + masterOptionTokenBalanceKey, masterProofTokenBalanceKey) = getOptionUserTokenBalanceKeys(registerBase.contractId.bytes.arr, + registerTarget.contractId.bytes.arr, registerOption.contractId.bytes.arr, + registerProof.contractId.bytes.arr, master) + + // Ensure that the final token balance values are correct + newState.tokenAccountBalance(masterBaseTokenBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractBaseTokenBalanceKey) shouldBe Long.MaxValue + + newState.tokenAccountBalance(masterTargetTokenBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractTargetTokenBalanceKey) shouldBe Long.MaxValue + + newState.tokenAccountBalance(masterOptionTokenBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractOptionTokenBalanceKey) shouldBe Long.MaxValue + + newState.tokenAccountBalance(masterProofTokenBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractProofTokenBalanceKey) shouldBe Long.MaxValue + } + } + } + + val preconditionsAndVOptionLargeAmountsCollect: Gen[(GenesisTransaction, RC, + RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- + createBaseTargetOptionProofTokenAndInitVOption( + Long.MaxValue, // baseTotalSupply + 1L, // baseUnity + Long.MaxValue, // baseIssueAmount + Long.MaxValue, // targetTotalSupply + 1L, // targetUnity + Long.MaxValue, // targetIssueAmount + Long.MaxValue, // optionTotalSupply + 1L, // optionUnity + Long.MaxValue, // proofTotalSupply + 1L, // proofUnity + Long.MaxValue, // baseTokenDepositAmount + Long.MaxValue, // targetTokenDepositAmount + Long.MaxValue, // optionTokenDepositAmount + Long.MaxValue) // proofTokenDepositAmount + + activateOption <- activateVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, Long.MaxValue, 1L, attach, fee, ts + 13) + mintOption <- mintVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, attach, fee, ts + 14) + collectOption <- collectVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, attach, fee, ts + 202) + + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, + issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activateOption, mintOption, collectOption) + + property("vOption able to collect very large numbers") { + forAll(preconditionsAndVOptionLargeAmountsCollect) { case (genesis: GenesisTransaction, registerBase: RC, registerTarget: RC, + registerOption: RC, registerProof: RC, registerVOption: RC, issueBase: EC, + issueTarget: EC, issueOption: EC, issueProof: EC, depositBase: EC, + depositTarget: EC, depositOption: EC, depositProof: EC, activate: EC, + mint: EC, collect: EC) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), + TestBlock.create(registerVOption.timestamp, Seq(registerBase, registerTarget, registerOption, registerProof, registerVOption, issueBase, issueTarget, + issueOption, issueProof, depositBase, depositTarget, depositOption, depositProof, activate, mint))), + TestBlock.createWithTxStatus(collect.timestamp, Seq(collect), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val user = registerBase.proofs.firstCurveProof.explicitGet().publicKey + val vOptionContractId = registerVOption.contractId.bytes.arr + + val (optionStatusKey, maxIssueNumKey, reservedOptionKey, + reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) = getOptionContractStateVarKeys(vOptionContractId) + + val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, + userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) + newState.contractNumInfo(reservedOptionKey) shouldBe 0L + newState.contractNumInfo(reservedProofKey) shouldBe Long.MaxValue + newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) + newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(tokenLockedKey) shouldBe 0L + + val master = registerVOption.proofs.firstCurveProof.explicitGet().publicKey + + val (contractBaseTokenBalanceKey, contractTargetTokenBalanceKey, + contractOptionTokenBalanceKey, contractProofTokenBalanceKey) = getOptionContractTokenBalanceKeys(registerBase.contractId.bytes.arr, + registerTarget.contractId.bytes.arr, registerOption.contractId.bytes.arr, + registerProof.contractId.bytes.arr, registerVOption.contractId.bytes.arr) + + val (masterBaseTokenBalanceKey, masterTargetTokenBalanceKey, + masterOptionTokenBalanceKey, masterProofTokenBalanceKey) = getOptionUserTokenBalanceKeys(registerBase.contractId.bytes.arr, + registerTarget.contractId.bytes.arr, registerOption.contractId.bytes.arr, + registerProof.contractId.bytes.arr, master) + + // Ensure that the final token balance values are correct + newState.tokenAccountBalance(masterBaseTokenBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractBaseTokenBalanceKey) shouldBe Long.MaxValue + + newState.tokenAccountBalance(masterTargetTokenBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractTargetTokenBalanceKey) shouldBe Long.MaxValue + + newState.tokenAccountBalance(masterOptionTokenBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractOptionTokenBalanceKey) shouldBe Long.MaxValue + + newState.tokenAccountBalance(masterProofTokenBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractProofTokenBalanceKey) shouldBe Long.MaxValue + } + } + } } From 656eb0226e46b1eff48a3a3e61d0d9def182f9fd Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Mon, 18 Jan 2021 13:52:54 +0800 Subject: [PATCH 195/391] Add activate boundary cases in VOptionInvalidDiffTest --- .../ExecuteVOptionInvalidDiffTest.scala | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index 696574ff7..aed41404d 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -47,21 +47,24 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } - val preconditionsAndVOptionActivate: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC,EC,EC)] = for { + val preconditionsAndVOptionActivate: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { (genesis, genesis2, master, user, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000, 1, 1000, 1000, 1, 1000, 1000, 1,1000, 1, 1000, 1000, 1000, 1000) activate <- activateVOptionGen(master, regVOptionContract.contractId, 1000, 1,1, attach, fee + 10000000000L, ts+13) activateInvalid <- activateVOptionGen(master, regVOptionContract.contractId, 10000, 1,1, attach, fee + 10000000000L, ts+13) activateInvalid2 <- activateVOptionGen(user, regVOptionContract.contractId, 1000, 1,1, attach, fee + 10000000000L, ts+13) + activateInvalid3 <- activateVOptionGen(master, regVOptionContract.contractId, 1000, 1,0, attach, fee + 10000000000L, ts+13) + activateInvalid4 <- activateVOptionGen(master, regVOptionContract.contractId, 1000, 0,1, attach, fee + 10000000000L, ts+13) + activateInvalid5 <- activateVOptionGen(master, regVOptionContract.contractId, 0, 1,1, attach, fee + 10000000000L, ts+13) } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, - issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, activateInvalid, activateInvalid2) + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, activateInvalid, activateInvalid2, activateInvalid3, activateInvalid4, activateInvalid5) property("unable to activate voption contract") { forAll(preconditionsAndVOptionActivate) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, - issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, activateInvalid: EC, activateInvalid2: EC) => + issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, activateInvalid: EC, activateInvalid2: EC, activateInvalid3: EC, activateInvalid4: EC, activateInvalid5: EC) => assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, @@ -87,6 +90,36 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller } + // activated with price unit zero + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(activateInvalid3.timestamp, Seq(activateInvalid3), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // activated with price zero + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(activateInvalid4.timestamp, Seq(activateInvalid4), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // activated with maxIssueNum zero + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(activateInvalid4.timestamp, Seq(activateInvalid5), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } } @@ -314,5 +347,4 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } } - } \ No newline at end of file From 58a8935e96e9409d1328ced7c91efc87b7eac65a Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 19 Jan 2021 12:24:37 +0800 Subject: [PATCH 196/391] solve new opc unspport issue --- src/test/scala/tools/ContractTranslator.scala | 55 ++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/src/test/scala/tools/ContractTranslator.scala b/src/test/scala/tools/ContractTranslator.scala index 789dec863..7627d3505 100644 --- a/src/test/scala/tools/ContractTranslator.scala +++ b/src/test/scala/tools/ContractTranslator.scala @@ -16,12 +16,13 @@ import vsys.blockchain.state.opcdiffs.TDBAROpcDiff.TDBARType import vsys.blockchain.state.opcdiffs.TDBOpcDiff.TDBType import vsys.blockchain.state.opcdiffs.TDBROpcDiff.TDBRType import vsys.blockchain.state.opcdiffs.SystemTransferDiff.TransferType +import vsys.blockchain.state.opcdiffs.IfOpcDiff.IfType import vsys.utils.serialization.Deser import scala.util.{Failure, Success, Try} object ContractTranslator extends App { - val bytes = ContractPaymentChannel.contract.bytes.arr + val bytes = ContractVSwap.contract.bytes.arr println(Base58.encode(bytes)) print("Contract Bytes Length:") @@ -62,7 +63,8 @@ object ContractTranslator extends App { val textual = Deser.parseArrays(bytes.slice(last, bytes.length)) val textualStr = textualFromBytes(textual) - val dataTypeList = Seq("PublicKey", "Address", "Amount", "Int32", "ShortText", "ContractAccount", "Account", "TokenId", "Timestamp", "Boolean", "ShortBytes") + val dataTypeList = Seq("DataTypeObj", "PublicKey", "Address", "Amount", "Int32", "ShortText", "ContractAccount", + "Account", "TokenId", "Timestamp", "Boolean", "ShortBytes", "Balance", "OpcBlock", "BigInt") val triggerTypeList = Seq("onInit trigger", "onDeposit trigger", "onWithdraw trigger") @@ -95,7 +97,7 @@ object ContractTranslator extends App { // print input variables val inputVarList = ftString(idx).slice(retNum + 1, ftString(idx).length) List.range(0, listParaTypes.size).foreach { i => - print(dataTypeList(listParaTypes(i) - 1) + " " + inputVarList(i)) + print(dataTypeList(listParaTypes(i)) + " " + inputVarList(i)) if (i < listParaTypes.size - 1) print(", ") } print(")") @@ -103,11 +105,11 @@ object ContractTranslator extends App { //print return variables if (listReturnTypes.length == 1) { print(" return ") - println(dataTypeList(listReturnTypes(0) - 1) + " " + ftString(idx)(0)) + println(dataTypeList(listReturnTypes(0)) + " " + ftString(idx)(0)) } else if (listReturnTypes.length > 1){ print(" return (") List.range(0, retNum).foreach { i => - print(dataTypeList(listReturnTypes(i) - 1) + " " + ftString(idx)(i)) + print(dataTypeList(listReturnTypes(i)) + " " + ftString(idx)(i)) if (i < listParaTypes.size - 1) print(", ") } println(")") @@ -178,16 +180,16 @@ object ContractTranslator extends App { printSeqSeqString(desc) println("State Variables:") List.range(0, stav.size).foreach { i => - println("%02d".format(i) + " | " + stav(i) + ": " + dataTypeList(stateVar(i)(1) - 1)) + println("%02d".format(i) + " | " + stav(i) + ": " + dataTypeList(stateVar(i)(1))) } println("State Maps:") List.range(0, stam.size).foreach { i => - println("%02d".format(i) + " | " + stam(i).head + " | " + stam(i)(1) + " -> " + stam(i)(2) + " | Map[" + dataTypeList(stateMap(i)(1) - 1) + ", " + dataTypeList(stateMap(i)(2) - 1) + "]") + println("%02d".format(i) + " | " + stam(i).head + " | " + stam(i)(1) + " -> " + stam(i)(2) + " | Map[" + dataTypeList(stateMap(i)(1)) + ", " + dataTypeList(stateMap(i)(2)) + "]") } } } - def strDataEntry(s: Array[Byte]): String = { + def strDataEntry(s: Array[Byte], nameList: Seq[String]): String = { var res = "DataEntry(" if (s(0) == DataType.Int32.id.toByte) { res = res + Ints.fromByteArray(s.tail).toString @@ -199,9 +201,24 @@ object ContractTranslator extends App { } else if (s(1) == 0.toByte) { res = res + "false" } + } else if (s(0) == DataType.OpcBlock.id.toByte) { + res = res + "Seq(\n" + val ifOpcLines = Deser.parseArrays(s.drop(3)) + ifOpcLines.foreach { case l => + res = res + " " + val x = opcToName(l, nameList) + res = res + x + "\n" + res = res + " | " + convertBytesToHex(l.slice(0, 2)) + "| " + res = res + convertBytesToHex(l.slice(2, l.length)) + "|\n" + } + res = res + "\n" + res = res + " )" + } else if (s(0) == DataType.DataTypeObj.id.toByte) { + res = res + "DataType." + res = res + dataTypeList(s(1).toInt) } res = res + ", " - res = res + dataTypeList(s(0).toInt - 1) + res = res + dataTypeList(s(0).toInt) res = res + ")" res } @@ -297,8 +314,11 @@ object ContractTranslator extends App { y match { case opcType: Byte if opcType == CDBVType.SetCDBV.id => "operation.db.setVariable(" + "db." + stateNameList(data(2)) + ", " + nameList(data(3)) + ")" case opcType: Byte if opcType == CDBVType.mapValueAddCDBV.id => "operation.db.mapValueAdd(" + "db." + stateMapList(data(2)) + ", " + nameList(data(3)) + ", " + nameList(data(4)) + ")" - case opcType: Byte if opcType == CDBVType.mapValueMinusCDBV.id => "operation.db.mapValueMinus(" + "db." + stateMapList(data(2)) + ", " + nameList(data(3)) + ", " + nameList(data(4)) + ")" - case opcType: Byte if opcType == CDBVType.mapSetCDBV.id => "operation.db.mapSet(" + "db." + stateMapList(data(2)) + ", " + nameList(data(3)) + ", " + nameList(data(4)) + ")" + case opcType: Byte if opcType == CDBVType.mapValueMinusCDBV.id => "operation.db.mapValueMinus(" + "db." + stateMapList(data(2)) + ", " + nameList(data(3)) + ", " + nameList(data(4)) + ")" + case opcType: Byte if opcType == CDBVType.mapSetCDBV.id => "operation.db.mapSet(" + "db." + stateMapList(data(2)) + ", " + nameList(data(3)) + ", " + nameList(data(4)) + ")" + case opcType: Byte if opcType == CDBVType.stateValueAddCDBV.id => "operation.db.stateValueAdd(" + "db." + stateNameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == CDBVType.stateValueMinusCDBV.id => "operation.db.stateValueMinus(" + "db." + stateNameList(data(2)) + ", " + nameList(data(3)) + ")" + case _ => "--- invalid opc code ---" } @@ -307,6 +327,7 @@ object ContractTranslator extends App { case opcType: Byte if opcType == CDBVRType.GetCDBVR.id => nameList(data(3)) + " = operation.db.getVariable(db." + stateNameList(data(2)) + ")" case opcType: Byte if opcType == CDBVRType.MapGetOrDefaultCDBVR.id => nameList(data(4)) + " = operation.db.mapGetOrDefault(db." + stateMapList(data(2)) + ", " + nameList(data(3)) + ")" case opcType: Byte if opcType == CDBVRType.MapGetCDVVR.id => nameList(data(4)) + " = operation.db.mapGet(db." + stateMapList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == CDBVRType.StateVarGetOrDefaultCDBVR.id => nameList(data(3)) + " = operation.db.stateGetOrDefault(db." + stateNameList(data(2)) + ")" case _ => "--- invalid opc code ---" } @@ -342,7 +363,9 @@ object ContractTranslator extends App { case opcType: Byte if opcType == OpcType.CompareOpc.id => y match { - case opcType: Byte if opcType == CompareType.Ge.id => nameList(data(4)) + " = operation.compare.greater(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == CompareType.Ge.id => nameList(data(4)) + " = operation.compare.greaterEqual(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == CompareType.Gt.id => nameList(data(4)) + " = operation.compare.greater(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == CompareType.Beq.id => nameList(data(4)) + " = operation.compare.bytesEqual(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case _ => "--- invalid opc code ---" } @@ -355,9 +378,15 @@ object ContractTranslator extends App { case opcType: Byte if opcType == BasicType.Minimum.id => nameList(data(4)) + " = operation.basic.minimum(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case opcType: Byte if opcType == BasicType.Maximum.id => nameList(data(4)) + " = operation.basic.maximum(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case opcType: Byte if opcType == BasicType.Concat.id => nameList(data(4)) + " = operation.basic.concat(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" - case opcType: Byte if opcType == BasicType.ConstantGet.id => nameList(data.last) + " = operation.basic.getConstant(" + strDataEntry(data.slice(2, data.length - 1)) + ")" + case opcType: Byte if opcType == BasicType.Convert.id => nameList(data(4)) + " = operation.basic.convert(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == BasicType.ConstantGet.id => nameList(data.last) + " = operation.basic.getConstant(" + strDataEntry(data.slice(2, data.length - 1), nameList) + ")" + case opcType: Byte if opcType == BasicType.SqrtBigInt.id => nameList(data(3)) + " = operation.basic.sqrt(" + nameList(data(2)) + ")" case _ => "--- invalid opc code ---" } + case opcType: Byte if opcType == OpcType.IfOpc.id => + y match { + case opcType: Byte if opcType == IfType.If.id => "operation.if(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + } case _ => "--- invalid opc code ---" From dee96de12fd8725fcf24aa6dc57c211382221f12 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 19 Jan 2021 13:05:52 +0800 Subject: [PATCH 197/391] Add invalid test cases with order factor --- .../ExecuteVOptionInvalidDiffTest.scala | 219 +++++++++++++----- 1 file changed, 158 insertions(+), 61 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index aed41404d..7e244be9f 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -22,23 +22,23 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec with VOptionFunctionHelperGen { private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) - val preconditionsAndVOptionDepositAndWithdrawBaseTargetTokens: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, EC, EC, EC, EC)] = for { - (genesis, genesis2, master, _, regBaseTokenContract, _, _, _, regVOptionContract, + val preconditionsAndVOptionDepositAndWithdrawBaseTargetTokens: Gen[(GenesisTransaction, RC, RC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, _, _, _, regVOptionContract, issueBaseToken, _, _, _, depositBaseToken, _, _, _, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000L, 1L, 1000L, 1000L, 1L, 1000L, 100L, 1L, 100L, 1L, 100L, 100L, 1000L, 1000L) withdrawBaseToken <- withdrawToken(master, regBaseTokenContract.contractId, regVOptionContract.contractId.bytes.arr, master.toAddress.bytes.arr, 100L, fee, ts + 13) withdrawInvalidBaseToken <- withdrawToken(master, regBaseTokenContract.contractId, regVOptionContract.contractId.bytes.arr, master.toAddress.bytes.arr, 2000L, fee, ts + 13) - } yield (genesis, genesis2, regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken, withdrawBaseToken, withdrawInvalidBaseToken) + } yield (genesis, regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken, withdrawBaseToken, withdrawInvalidBaseToken) // withdraw base tokens property("withdraw base tokens more than depositing in voption contract") { - forAll(preconditionsAndVOptionDepositAndWithdrawBaseTargetTokens) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, + forAll(preconditionsAndVOptionDepositAndWithdrawBaseTargetTokens) { case (genesis: GenesisTransaction, regBaseTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, depositBaseToken: EC, withdrawBaseToken: EC, withdrawInvalidBaseToken: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBaseToken.timestamp, Seq(regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken))), TestBlock.createWithTxStatus(withdrawBaseToken.timestamp, Seq(withdrawBaseToken), TransactionStatus.Success)) { (blockDiffEi) => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositBaseToken.timestamp, Seq(regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBaseToken.timestamp, Seq(regBaseTokenContract, regVOptionContract, issueBaseToken, depositBaseToken))), TestBlock.createWithTxStatus(withdrawInvalidBaseToken.timestamp, Seq(withdrawInvalidBaseToken), TransactionStatus.ContractTokenBalanceInsufficient)) { (blockDiffEi) => blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false @@ -66,14 +66,14 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, activateInvalid: EC, activateInvalid2: EC, activateInvalid3: EC, activateInvalid4: EC, activateInvalid5: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken))), TestBlock.createWithTxStatus(activate.timestamp, Seq(activate), TransactionStatus.Success)) { (blockDiffEi) => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } // activate amount more than depositing in voption contract - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken))), TestBlock.createWithTxStatus(activateInvalid.timestamp, Seq(activateInvalid), TransactionStatus.Failed)) { (blockDiffEi) => @@ -82,7 +82,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed } // activated by another user - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken))), TestBlock.createWithTxStatus(activateInvalid2.timestamp, Seq(activateInvalid2), TransactionStatus.ContractInvalidCaller)) { (blockDiffEi) => @@ -91,7 +91,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller } // activated with price unit zero - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken))), TestBlock.createWithTxStatus(activateInvalid3.timestamp, Seq(activateInvalid3), TransactionStatus.Failed)) { (blockDiffEi) => @@ -101,7 +101,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } // activated with price zero - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken))), TestBlock.createWithTxStatus(activateInvalid4.timestamp, Seq(activateInvalid4), TransactionStatus.Failed)) { (blockDiffEi) => @@ -111,10 +111,10 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } // activated with maxIssueNum zero - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken))), - TestBlock.createWithTxStatus(activateInvalid4.timestamp, Seq(activateInvalid5), TransactionStatus.Failed)) { (blockDiffEi) => + TestBlock.createWithTxStatus(activateInvalid5.timestamp, Seq(activateInvalid5), TransactionStatus.Failed)) { (blockDiffEi) => blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed @@ -123,8 +123,8 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } - val preconditionsAndVOptionMint: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { - (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + val preconditionsAndVOptionMint: Gen[(GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000, 1, 1000, 1000, 1, 1000, 100, 1,100, 1, 1000, 1000, 100, 100) @@ -133,24 +133,35 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec mintInvalid <- mintVOptionGen(master, regVOptionContract.contractId, 1000, attach, fee + 10000000000L, ts+14) mintInvalid2 <- mintVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+101) mintInvalid3 <- mintVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+201) - } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, mintInvalid, mintInvalid2, mintInvalid3) property("unable to mint voption") { - forAll(preconditionsAndVOptionMint) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + forAll(preconditionsAndVOptionMint) { case (genesis: GenesisTransaction, regBaseTokenContract: RC, regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, mint: EC, mintInvalid: EC, mintInvalid2: EC, mintInvalid3: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate))), TestBlock.createWithTxStatus(mint.timestamp, Seq(mint), TransactionStatus.Success)) { (blockDiffEi) => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } + + // mint before activate + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(mint.timestamp, Seq(mint), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // mint voption is greater than maxIssueNum - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate))), TestBlock.createWithTxStatus(mintInvalid.timestamp, Seq(mintInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => @@ -159,7 +170,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } // mint after executeTime - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate))), TestBlock.createWithTxStatus(mintInvalid2.timestamp, Seq(mintInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => @@ -168,7 +179,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } // mint after executeDeadline - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate))), TestBlock.createWithTxStatus(mintInvalid3.timestamp, Seq(mintInvalid3), TransactionStatus.Failed)) { (blockDiffEi, _) => @@ -179,8 +190,8 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } - val preconditionsAndVOptionUnlock: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { - (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + val preconditionsAndVOptionUnlock: Gen[(GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000, 1, 1000, 1000, 1, 1000, 100, 1,100, 1, 1000, 1000, 100, 100) @@ -189,23 +200,44 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec unlock <- unlockVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+14) unlockInvalid <- unlockVOptionGen(master, regVOptionContract.contractId, 100, attach, fee + 10000000000L, ts+14) unlockInvalid2 <- unlockVOptionGen(master, regVOptionContract.contractId, 10, attach, fee + 10000000000L, ts+201) - } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, unlock, unlockInvalid, unlockInvalid2) property("unable to unlock") { - forAll(preconditionsAndVOptionUnlock) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + forAll(preconditionsAndVOptionUnlock) { case (genesis: GenesisTransaction, regBaseTokenContract: RC, regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, mint: EC, unlock: EC, unlockInvalid: EC, unlockInvalid2: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint))), TestBlock.createWithTxStatus(unlock.timestamp, Seq(unlock), TransactionStatus.Success)) { (blockDiffEi) => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } + + // unlock before activate + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(unlock.timestamp, Seq(unlock), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // unlock before mint + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate))), + TestBlock.createWithTxStatus(unlock.timestamp, Seq(unlock), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // unlock voption greater than mint amount - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint))), TestBlock.createWithTxStatus(unlockInvalid.timestamp, Seq(unlockInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi) => @@ -214,7 +246,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } // unlock voption after executedeadline - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regVOptionContract.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint))), TestBlock.createWithTxStatus(unlockInvalid2.timestamp, Seq(unlockInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => @@ -225,8 +257,8 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } - val preconditionsAndVOptionExecute: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { - (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + val preconditionsAndVOptionExecute: Gen[(GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000L, 1L, 1000L, 1000L, 1L, 1000L, 1000L, 1L,1000L, 1L, 1000L, 1000L, 1000, 1000) @@ -237,23 +269,44 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec executeInvalid <- executeVOptionGen(master, regVOptionContract.contractId, 1000L, attach, fee + 10000000000L, ts+101) executeInvalid2 <- executeVOptionGen(master, regVOptionContract.contractId, 1000L, attach, fee + 10000000000L, ts+99) executeInvalid3 <- executeVOptionGen(master, regVOptionContract.contractId, 1000L, attach, fee + 10000000000L, ts+201) - } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, execute, executeInvalid, executeInvalid2, executeInvalid3) property("unable to execute voption") { - forAll(preconditionsAndVOptionExecute) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + forAll(preconditionsAndVOptionExecute) { case (genesis: GenesisTransaction, regBaseTokenContract: RC, regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, activate: EC, mint: EC, execute: EC, executeInvalid: EC, executeInvalid2: EC, executeInvalid3: EC) => - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint))), TestBlock.createWithTxStatus(execute.timestamp, Seq(execute), TransactionStatus.Success)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success } + + // execute voption before activate + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken))), + TestBlock.createWithTxStatus(execute.timestamp, Seq(execute), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // execute before mint + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate))), + TestBlock.createWithTxStatus(execute.timestamp, Seq(execute), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // execute voption more than target token balance - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint))), TestBlock.createWithTxStatus(executeInvalid.timestamp, Seq(executeInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => @@ -262,7 +315,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } // execute voption before execute time - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint))), TestBlock.createWithTxStatus(executeInvalid2.timestamp, Seq(executeInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => @@ -271,7 +324,7 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } // execute voption after execute deadline - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint))), TestBlock.createWithTxStatus(executeInvalid3.timestamp, Seq(executeInvalid3), TransactionStatus.Failed)) { (blockDiffEi, _) => @@ -281,70 +334,114 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } } - val preconditionsAndVOptionCollect: Gen[(GenesisTransaction, GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { - (genesis, genesis2, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + val preconditionsAndVOptionCollect: Gen[(GenesisTransaction, RC, RC, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, fee, ts, attach) <- createBaseTargetOptionProofTokenAndInitVOption(1000L, 1L, 1000L, 1000L, 1L, 1000L, 1000L, 1L,1000L, 1L, 1000L, 1000L, 1000, 1000) activate <- activateVOptionGen(master, regVOptionContract.contractId, 1000L, 10L,1L, attach, fee + 10000000000L, ts+13) mint <- mintVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+14) - execute <- executeVOptionGen(master, regVOptionContract.contractId, 2L, attach, fee + 10000000000L, ts+199) + unlock <- unlockVOptionGen(master, regVOptionContract.contractId, 100, attach, fee + 10000000000L, ts+15) + collect <- collectVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+100000000) collectInvalid <- collectVOptionGen(master, regVOptionContract.contractId, 1000L, attach, fee + 10000000000L, ts+100000000) collectInvalid2 <- collectVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+99) collectInvalid3 <- collectVOptionGen(master, regVOptionContract.contractId, 100L, attach, fee + 10000000000L, ts+199) - - } yield (genesis, genesis2, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, - issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint, execute, collect, collectInvalid, collectInvalid2, collectInvalid3) + collectInvalid4 <- collectVOptionGen(master, regVOptionContract.contractId, 0L, attach, fee + 10000000000L, ts+100000000) + } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, + issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, + activate, mint, unlock, collect, collectInvalid, collectInvalid2, collectInvalid3, collectInvalid4) property("unable to collect voption") { - forAll(preconditionsAndVOptionCollect) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regBaseTokenContract: RC, + forAll(preconditionsAndVOptionCollect) { case (genesis: GenesisTransaction, regBaseTokenContract: RC, regTargetTokenContract: RC, regOptionTokenContract: RC, regProofTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, issueTargetToken: EC, issueOptionToken: EC, issueProofToken: EC, depositBaseToken: EC, depositTargetToken: EC, depositOptionToken: EC, depositProofToken: EC, - activate: EC, mint: EC, execute: EC, collect: EC, collectInvalid: EC, collectInvalid2: EC, collectInvalid3: EC) => + activate: EC, mint: EC, unlock: EC, collect: EC, collectInvalid: EC, collectInvalid2: EC, collectInvalid3: EC, collectInvalid4: EC) => - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint)), - TestBlock.create(execute.timestamp, Seq()), - TestBlock.create(execute.timestamp+1, Seq(execute))), - TestBlock.createWithTxStatus(collect.timestamp, Seq(collect), TransactionStatus.Success)) { (blockDiffEi, _) => + TestBlock.create(collect.timestamp, Seq())), + TestBlock.createWithTxStatus(collect.timestamp+1, Seq(collect), TransactionStatus.Success)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success } + // collect voption before activate + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositProofToken.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken)), + TestBlock.create(collect.timestamp, Seq())), + TestBlock.createWithTxStatus(collect.timestamp+1, Seq(collect), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // collect voption before mint + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(activate.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate)), + TestBlock.create(collect.timestamp, Seq())), + TestBlock.createWithTxStatus(collect.timestamp+1, Seq(collect), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // collect voption after unlock + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(unlock.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint, unlock)), + TestBlock.create(collect.timestamp, Seq())), + TestBlock.createWithTxStatus(collect.timestamp+1, Seq(collect), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // collect voption more than mint amount - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint)), - TestBlock.create(execute.timestamp, Seq()), - TestBlock.create(execute.timestamp+1, Seq(execute))), - TestBlock.createWithTxStatus(collectInvalid.timestamp, Seq(collectInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => + TestBlock.create(collectInvalid.timestamp, Seq())), + TestBlock.createWithTxStatus(collectInvalid.timestamp+1, Seq(collectInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } // collect voption before execute time - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint)), - TestBlock.create(execute.timestamp, Seq()), - TestBlock.create(execute.timestamp+1, Seq(execute))), - TestBlock.createWithTxStatus(collectInvalid2.timestamp, Seq(collectInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => + TestBlock.create(collectInvalid2.timestamp, Seq())), + TestBlock.createWithTxStatus(collectInvalid2.timestamp+1, Seq(collectInvalid2), TransactionStatus.Failed)) { (blockDiffEi, _) => blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } // collect voption after execute deadline - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, + regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, + depositOptionToken, depositProofToken, activate, mint)), + TestBlock.create(collectInvalid3.timestamp, Seq())), + TestBlock.createWithTxStatus(collectInvalid3.timestamp+1, Seq(collectInvalid3), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true + blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // collect zero amount after collecting all amount + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(mint.timestamp, Seq(regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activate, mint)), - TestBlock.create(execute.timestamp, Seq()), - TestBlock.create(execute.timestamp+1, Seq(execute))), - TestBlock.createWithTxStatus(collectInvalid3.timestamp, Seq(collectInvalid3), TransactionStatus.Failed)) { (blockDiffEi, _) => + TestBlock.create(collect.timestamp, Seq()), + TestBlock.create(collect.timestamp, Seq(collect)), + TestBlock.create(collectInvalid4.timestamp, Seq())), + TestBlock.createWithTxStatus(collectInvalid4.timestamp+1, Seq(collectInvalid4), TransactionStatus.Failed)) { (blockDiffEi, _) => blockDiffEi.txsDiff.contractNumDB.isEmpty shouldBe true blockDiffEi.txsDiff.portfolios.isEmpty shouldBe false blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } } } -} \ No newline at end of file +} From fed1646d5a9828a79a0a37e4edc0bd6052fb11bd Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 22 Jan 2021 12:52:38 +0800 Subject: [PATCH 198/391] add shwo hex config --- src/test/scala/tools/ContractTranslator.scala | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/test/scala/tools/ContractTranslator.scala b/src/test/scala/tools/ContractTranslator.scala index 7627d3505..2a8a32549 100644 --- a/src/test/scala/tools/ContractTranslator.scala +++ b/src/test/scala/tools/ContractTranslator.scala @@ -22,7 +22,8 @@ import vsys.utils.serialization.Deser import scala.util.{Failure, Success, Try} object ContractTranslator extends App { - val bytes = ContractVSwap.contract.bytes.arr + val bytes = ContractVOption.contract.bytes.arr + val showHex = false println(Base58.encode(bytes)) print("Contract Bytes Length:") @@ -106,7 +107,7 @@ object ContractTranslator extends App { if (listReturnTypes.length == 1) { print(" return ") println(dataTypeList(listReturnTypes(0)) + " " + ftString(idx)(0)) - } else if (listReturnTypes.length > 1){ + } else if (listReturnTypes.length > 1) { print(" return (") List.range(0, retNum).foreach { i => print(dataTypeList(listReturnTypes(i)) + " " + ftString(idx)(i)) @@ -116,24 +117,28 @@ object ContractTranslator extends App { } else println() // print function or trigger head opc - print("| ") - print(convertBytesToHex(Shorts.toByteArray(funcIdx))) - print("| ") - print(convertBytesToHex(Array(funcType))) - print("| ") - print(convertBytesToHex(listParaTypes)) - print("| ") - print(convertBytesToHex(listReturnTypes)) - println("|") + if (showHex) { + print("| ") + print(convertBytesToHex(Shorts.toByteArray(funcIdx))) + print("| ") + print(convertBytesToHex(Array(funcType))) + print("| ") + print(convertBytesToHex(listParaTypes)) + print("| ") + print(convertBytesToHex(listReturnTypes)) + println("|") + } // print opc lines listOpcLines.foreach { case l => print(" ") val x = opcToName(l, inputVarList) println(x) - print(" | " + convertBytesToHex(l.slice(0, 2))) - print("| ") - println(convertBytesToHex(l.slice(2, l.length)) + "|") + if (showHex) { + print(" | " + convertBytesToHex(l.slice(0, 2))) + print("| ") + println(convertBytesToHex(l.slice(2, l.length)) + "|") + } } println() } @@ -208,8 +213,10 @@ object ContractTranslator extends App { res = res + " " val x = opcToName(l, nameList) res = res + x + "\n" - res = res + " | " + convertBytesToHex(l.slice(0, 2)) + "| " - res = res + convertBytesToHex(l.slice(2, l.length)) + "|\n" + if (showHex) { + res = res + " | " + convertBytesToHex(l.slice(0, 2)) + "| " + res = res + convertBytesToHex(l.slice(2, l.length)) + "|\n" + } } res = res + "\n" res = res + " )" From bd1202212e2041b3bae3f82bf9c8047f22b81aa4 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:24:23 +0800 Subject: [PATCH 199/391] change address to account --- src/main/scala/vsys/blockchain/state/Diff.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/Diff.scala b/src/main/scala/vsys/blockchain/state/Diff.scala index 1883e9670..f1b9d08b9 100644 --- a/src/main/scala/vsys/blockchain/state/Diff.scala +++ b/src/main/scala/vsys/blockchain/state/Diff.scala @@ -89,7 +89,7 @@ object Diff { contractTokens: Map[ByteStr, Int] = Map.empty, tokenDB: Map[ByteStr, Array[Byte]] = Map.empty, tokenAccountBalance: Map[ByteStr, Long] = Map.empty, - relatedAddress: Map[Address, Boolean] = Map.empty, + relatedAddress: Map[Account, Boolean] = Map.empty, dbEntries: Map[ByteStr, Entry] = Map.empty, leaseState: Map[ByteStr, Boolean] = Map.empty): Diff = Diff( transactions = Map((tx.id, (height, ProcessedTransaction(txStatus, chargedFee, tx), (portfolios.keys ++ relatedAddress.keys).toSet))), From 01bff7a2653bc98bef7542ff7cdaefb42c7314d3 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:26:41 +0800 Subject: [PATCH 200/391] opcdiff related adds to accs --- src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiff.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiff.scala index 139dbb542..31a2b659a 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiff.scala @@ -4,7 +4,7 @@ import cats.Monoid import cats.implicits._ import vsys.blockchain.state.{BlockDiff, ByteStr, Diff, Portfolio} import vsys.blockchain.transaction.Transaction -import vsys.account.{Account, Address} +import vsys.account.Account case class OpcDiff(contractDB: Map[ByteStr, Array[Byte]] = Map.empty, contractNumDB: Map[ByteStr, Long] = Map.empty, @@ -12,7 +12,7 @@ case class OpcDiff(contractDB: Map[ByteStr, Array[Byte]] = Map.empty, contractTokens: Map[ByteStr, Int] = Map.empty, tokenDB: Map[ByteStr, Array[Byte]] = Map.empty, tokenAccountBalance: Map[ByteStr, Long] = Map.empty, - relatedAddress: Map[Address, Boolean] = Map.empty, + relatedAddress: Map[Account, Boolean] = Map.empty, portfolios: Map[Account, Portfolio] = Map.empty ) { From b11cbe1b859bcf545b6e3212606b4ea99b82b085 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:39:31 +0800 Subject: [PATCH 201/391] fix bug --- .../vsys/blockchain/state/opcdiffs/SystemTransferDiff.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiff.scala index e7361a007..59a323d5a 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/SystemTransferDiff.scala @@ -54,7 +54,7 @@ object SystemTransferDiff extends OpcDiffer { _ <- Either.cond(Try(Math.addExact(transferAmount, recipientBalance)).isSuccess, (), OverflowError) _ <- Either.cond(transferAmount >= 0, (), ContractInvalidAmount) senderCallDiff <- getTriggerCallOpcDiff(context, OpcDiff.empty, sender, recipient, amount, sysTokenId, CallType.Trigger, 2) - senderRelatedAddress = if (sender.dataType == DataType.Address) Map(Address.fromBytes(sender.data).explicitGet() -> true) else Map[Address, Boolean]() + senderRelatedAddress = if (sender.dataType == DataType.Address) Map(Account.fromBytes(sender.data,0).explicitGet()._1 -> true) else Map[Account, Boolean]() senderPortDiff: Map[Account, Portfolio] = Map( senderAddr._1 -> Portfolio( balance = -transferAmount, @@ -63,7 +63,7 @@ object SystemTransferDiff extends OpcDiffer { senderDiff = OpcDiff(relatedAddress = senderRelatedAddress, portfolios = senderPortDiff) senderTotalDiff = OpcDiff.opcDiffMonoid.combine(senderCallDiff, senderDiff) recipientCallDiff <- getTriggerCallOpcDiff(context, senderTotalDiff, sender, recipient, amount, sysTokenId, CallType.Trigger, 1) - recipientRelatedAddress = if (recipient.dataType == DataType.Address) Map(Address.fromBytes(recipient.data).explicitGet() -> true) else Map[Address, Boolean]() + recipientRelatedAddress = if (recipient.dataType == DataType.Address) Map(Account.fromBytes(recipient.data,0).explicitGet()._1 -> true) else Map[Account, Boolean]() recipientPortDiff: Map[Account, Portfolio] = Map( recipientAddr._1 -> Portfolio( balance = transferAmount, From dab49548635c8890e46992dcde26d02ccb5e5d31 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:40:00 +0800 Subject: [PATCH 202/391] fix bug --- .../scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala index 80131c2e3..f35db8227 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala @@ -3,7 +3,7 @@ package vsys.blockchain.state.opcdiffs import cats.Monoid import com.google.common.primitives.{Bytes, Ints, Longs} import vsys.blockchain.state._ -import vsys.account.{Address, ContractAccount} +import vsys.account.{Account, Address, ContractAccount} import vsys.blockchain.transaction.ValidationError import vsys.blockchain.transaction.ValidationError._ import vsys.account.ContractAccount.tokenIdFromBytes @@ -131,12 +131,12 @@ object TDBAOpcDiff extends OpcDiffer { // relatedContract needed for { senderCallDiff <- getTriggerCallOpcDiff(context, OpcDiff.empty, sender, recipient, amount, tokenIdDataEntry, CallType.Trigger, 2) - senderRelatedAddress = if (sender.dataType == DataType.Address) Map(Address.fromBytes(sender.data).explicitGet() -> true) else Map[Address, Boolean]() + senderRelatedAddress = if (sender.dataType == DataType.Address) Map(Account.fromBytes(sender.data,0).explicitGet()._1 -> true) else Map[Account, Boolean]() senderDiff = OpcDiff(relatedAddress = senderRelatedAddress, tokenAccountBalance = Map(senderBalanceKey -> -transferAmount)) senderTotalDiff = OpcDiff.opcDiffMonoid.combine(senderCallDiff, senderDiff) recipientCallDiff <- getTriggerCallOpcDiff(context, senderTotalDiff, sender, recipient, amount, tokenIdDataEntry, CallType.Trigger, 1) - recipientRelatedAddress = if (recipient.dataType == DataType.Address) Map(Address.fromBytes(recipient.data).explicitGet() -> true) else Map[Address, Boolean]() + recipientRelatedAddress = if (recipient.dataType == DataType.Address) Map(Account.fromBytes(recipient.data,0).explicitGet()._1 -> true) else Map[Account, Boolean]() recipientDiff = OpcDiff(relatedAddress = recipientRelatedAddress, tokenAccountBalance = Map(recipientBalanceKey -> transferAmount)) returnDiff = Monoid.combineAll(Seq(senderTotalDiff, recipientCallDiff, recipientDiff)) From 35f883ab2b320333c0a995e60ce4b5c82ace4963 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:46:11 +0800 Subject: [PATCH 203/391] add contract address related tx ids --- .../state/diffs/ExecuteContractFunctionTransactionDiff.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/diffs/ExecuteContractFunctionTransactionDiff.scala b/src/main/scala/vsys/blockchain/state/diffs/ExecuteContractFunctionTransactionDiff.scala index ee298bd84..3f966e3d6 100644 --- a/src/main/scala/vsys/blockchain/state/diffs/ExecuteContractFunctionTransactionDiff.scala +++ b/src/main/scala/vsys/blockchain/state/diffs/ExecuteContractFunctionTransactionDiff.scala @@ -30,7 +30,7 @@ object ExecuteContractFunctionTransactionDiff { contractNumDB = diff.contractNumDB, contractStateDB = diff.contractStateDB, contractTokens = diff.contractTokens, - relatedAddress = diff.relatedAddress, + relatedAddress = diff.relatedAddress ++ Map(exContext.contractId -> true), chargedFee = tx.transactionFee )) .left.flatMap( e => From e3c4e9751bcaece82fb7e0f97e7d5ddfa52327e5 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:46:26 +0800 Subject: [PATCH 204/391] add contract address related tx ids --- .../state/diffs/RegisterContractTransactionDiff.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/diffs/RegisterContractTransactionDiff.scala b/src/main/scala/vsys/blockchain/state/diffs/RegisterContractTransactionDiff.scala index 8e7671b2f..d298d3ee7 100644 --- a/src/main/scala/vsys/blockchain/state/diffs/RegisterContractTransactionDiff.scala +++ b/src/main/scala/vsys/blockchain/state/diffs/RegisterContractTransactionDiff.scala @@ -34,7 +34,7 @@ object RegisterContractTransactionDiff { contractTokens = diff.contractTokens, tokenDB = diff.tokenDB, tokenAccountBalance = diff.tokenAccountBalance, - relatedAddress = diff.relatedAddress, + relatedAddress = diff.relatedAddress ++ Map(exContext.contractId -> true), chargedFee = tx.transactionFee )) .left.flatMap( e => From 0b0593d35b625128f2ed620070e072edd6379e7e Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:47:56 +0800 Subject: [PATCH 205/391] add contract adds related tx ids setting to db --- src/main/scala/vsys/blockchain/state/StateWriter.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/StateWriter.scala b/src/main/scala/vsys/blockchain/state/StateWriter.scala index 18f2ed7ae..1841e221c 100644 --- a/src/main/scala/vsys/blockchain/state/StateWriter.scala +++ b/src/main/scala/vsys/blockchain/state/StateWriter.scala @@ -1,8 +1,8 @@ package vsys.blockchain.state import java.util.concurrent.locks.ReentrantReadWriteLock - import cats.implicits._ +import vsys.account.Address import vsys.blockchain.state.reader.StateReaderImpl import vsys.utils.ScorexLogging import vsys.settings.StateSettings @@ -45,14 +45,15 @@ class StateWriterImpl(p: StateStorage, synchronizationToken: ReentrantReadWriteL } measureSizeLog("accountTransactionIds")(blockDiff.txsDiff.accountTransactionIds) { - _.foreach { case (acc, txIds) => + _.foreach { case (acc, txIds) => if (stateSettings.txContractTxIds || acc.bytes.arr(0) == Address.AddressVersion) { val startIdxShift = sp().accountTransactionsLengths.get(acc.bytes).getOrElse(0) txIds.reverse.foldLeft(startIdxShift) { case (shift, txId) => sp().accountTransactionIds.put(accountIndexKey(acc, shift), txId) - shift + 1 + shift + 1 } sp().accountTransactionsLengths.put(acc.bytes, startIdxShift + txIds.length) } + } } if(stateSettings.txTypeAccountTxIds) { From c02115556fc8c8db3eb075a28f67498d2ec48249 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:55:08 +0800 Subject: [PATCH 206/391] add txContractTxIds to statesetting --- src/main/scala/vsys/settings/BlockchainSettings.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/settings/BlockchainSettings.scala b/src/main/scala/vsys/settings/BlockchainSettings.scala index da0acc23d..5610f2fb7 100644 --- a/src/main/scala/vsys/settings/BlockchainSettings.scala +++ b/src/main/scala/vsys/settings/BlockchainSettings.scala @@ -30,7 +30,8 @@ object FunctionalitySettings { val configPath = "vsys.blockchain.custom.functionality" } -case class StateSettings(txTypeAccountTxIds: Boolean) +case class StateSettings(txTypeAccountTxIds: Boolean, + txContractTxIds: Boolean) object StateSettings { val configPath = "vsys.blockchain.state" From d5778ec3c326455bbcce5629fcef12ee9984b7a6 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 11:59:05 +0800 Subject: [PATCH 207/391] add contract adds tx ids config --- src/main/resources/application.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index bc7d34918..3699fe555 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -160,6 +160,7 @@ vsys { state { # turn on/off the state of transactions grouped by address and transaction type tx-type-account-tx-ids = off + tx-contract-tx-ids = off } } From 3b3317640f053fab1852bd7237fc11c264c4bfbd Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 12:00:14 +0800 Subject: [PATCH 208/391] change adds to accounts --- src/main/scala/vsys/api/http/TransactionsApiRoute.scala | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala index 45fc2f516..a02017d42 100644 --- a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala +++ b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala @@ -1,18 +1,17 @@ package vsys.api.http import javax.ws.rs.Path - import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.Route import io.swagger.annotations._ import play.api.libs.json._ -import vsys.account.Address +import vsys.account.{Account, Address} import vsys.blockchain.history.History import vsys.blockchain.state.ByteStr import vsys.blockchain.state.reader.StateReader import vsys.blockchain.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} import vsys.blockchain.transaction.TransactionParser.TransactionType -import vsys.blockchain.transaction.{Transaction, ProcessedTransaction} +import vsys.blockchain.transaction.{ProcessedTransaction, Transaction} import vsys.blockchain.UtxPool import vsys.settings.{RestAPISettings, StateSettings} @@ -95,7 +94,7 @@ case class TransactionsApiRoute( )) def transactionList: Route = (path("list") & get) { parameters(('address, 'txType.?, 'limit, 'offset ? "0")) { (addressStr, txTypeStrOpt, limitStr, offsetStr) => - Address.fromString(addressStr) match { + Account.fromString(addressStr) match { case Left(e) => complete(ApiError.fromValidationError(e)) case Right(a) => Exception.allCatch.opt(limitStr.toInt) match { @@ -138,7 +137,7 @@ case class TransactionsApiRoute( //remove after all related productions being updated def addressLimit: Route = (pathPrefix("address") & get) { pathPrefix(Segment) { address => - Address.fromString(address) match { + Account.fromString(address) match { case Left(e) => complete(ApiError.fromValidationError(e)) case Right(a) => pathPrefix("limit") { From 45ea78e4b3ef10396b7aac782e62459c1a101995 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 12:01:12 +0800 Subject: [PATCH 209/391] fix bugs --- .../scala/vsys/api/http/TransactionsRouteSpec.scala | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/api/http/TransactionsRouteSpec.scala b/src/test/scala/vsys/api/http/TransactionsRouteSpec.scala index ae5f4e36b..6813ccddf 100644 --- a/src/test/scala/vsys/api/http/TransactionsRouteSpec.scala +++ b/src/test/scala/vsys/api/http/TransactionsRouteSpec.scala @@ -34,8 +34,14 @@ class TransactionsRouteSpec extends RouteSpec("/transactions") routePath("/address/{address}/limit/{limit}") - { "handles invalid address" in { - forAll(bytes32gen, choose(1, MaxTransactionsPerRequest)) { case (bytes, limit) => - Get(routePath(s"/address/${Base58.encode(bytes)}/limit/$limit")) ~> route should produce(InvalidAddress) + forAll(fakeAddressGen, choose(1, MaxTransactionsPerRequest)) { case (bytes, limit) => + Get(routePath(s"/address/$bytes/limit/$limit")) ~> route should produce(InvalidAddress) + } + } + + "handles invalid contract address" in { + forAll(fakeAccountGen, choose(1, MaxTransactionsPerRequest)) { case (bytes, limit) => + Get(routePath(s"/address/$bytes/limit/$limit")) ~> route should produce(InvalidContractAddress) } } From db60ca82085d4858e2a646ce0a21582c2ee2ed4a Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 25 Jan 2021 12:03:02 +0800 Subject: [PATCH 210/391] update unit tests for state setting change --- .../scala/vsys/blockchain/transaction/TransactionGen.scala | 7 ++++++- .../vsys/settings/BlockchainSettingsSpecification.scala | 2 ++ src/test/scala/vsys/settings/TestStateSettings.scala | 6 ++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala b/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala index 89f03775b..709b7696a 100644 --- a/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala +++ b/src/test/scala/vsys/blockchain/transaction/TransactionGen.scala @@ -2,11 +2,12 @@ package vsys.blockchain.transaction import org.scalacheck.Gen.{alphaLowerChar, frequency, numChar} import org.scalacheck.{Arbitrary, Gen} +import scorex.crypto.encode.Base58 import vsys.account.PublicKeyAccount._ import vsys.account._ import vsys.blockchain.consensus.SPoSCalc._ import vsys.blockchain.contract._ -import vsys.blockchain.database.{DataType => DatabaseDataType, Entry} +import vsys.blockchain.database.{Entry, DataType => DatabaseDataType} import vsys.blockchain.state._ import vsys.blockchain.transaction.contract._ import vsys.blockchain.transaction.database.DbPutTransaction @@ -39,6 +40,10 @@ trait TransactionGen { val ntpTimestampGen: Gen[Long] = Gen.choose(1, 1000).map(NTP.correctedTime() - _) val accountGen: Gen[PrivateKeyAccount] = bytes32gen.map(seed => PrivateKeyAccount(seed)) + + val fakeAddressGen: Gen[String] = bytes32gen.map(seed => 'A' +: Base58.encode(seed.tail)) + + val fakeAccountGen: Gen[String] = bytes32gen.map(seed => 'C' +: Base58.encode(seed.tail)) val contractAccountGen: Gen[ContractAccount] = Gen.const(ContractAccount.fromId(ByteStr(bytes32gen.sample.get))) diff --git a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala index 44e2ad98a..8ac4af525 100644 --- a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala +++ b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala @@ -51,6 +51,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { | } | state { | tx-type-account-tx-ids = on + | tx-contract-tx-ids = on | } | } |}""".stripMargin)) @@ -84,6 +85,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { | type = TESTNET | state { | tx-type-account-tx-ids = off + | tx-contract-tx-ids = off | } | } |}""".stripMargin)) diff --git a/src/test/scala/vsys/settings/TestStateSettings.scala b/src/test/scala/vsys/settings/TestStateSettings.scala index 601009f44..6c048ddb4 100644 --- a/src/test/scala/vsys/settings/TestStateSettings.scala +++ b/src/test/scala/vsys/settings/TestStateSettings.scala @@ -2,9 +2,11 @@ package vsys.settings object TestStateSettings { val AllOn = StateSettings( - txTypeAccountTxIds = true + txTypeAccountTxIds = true, + txContractTxIds = true ) val AllOff = StateSettings( - txTypeAccountTxIds = false + txTypeAccountTxIds = false, + txContractTxIds = false ) } From 9b7e56531ae375dbeeb1313dd9aeeadf31aad2ec Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 27 Jan 2021 16:10:47 +0800 Subject: [PATCH 211/391] add address limit to contract api --- .../api/http/contract/ContractApiRoute.scala | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 9ff9a14b1..8dec37f74 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -7,7 +7,7 @@ import akka.http.scaladsl.server.Route import com.google.common.primitives.Ints import io.netty.channel.group.ChannelGroup import io.swagger.annotations._ -import play.api.libs.json.{Format, JsArray, JsNumber, JsObject, Json} +import play.api.libs.json.{Format, JsArray, JsNull, JsNumber, JsObject, JsValue, Json} import vsys.account.{Account, ContractAccount} import vsys.account.ContractAccount.{contractIdFromBytes, tokenIdFromBytes} import vsys.api.http._ @@ -24,6 +24,7 @@ import vsys.wallet.Wallet import scala.util.Success import scala.util.control.Exception import ContractApiRoute._ +import vsys.blockchain.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} @Path("/contract") @Api(value = "/contract") @@ -31,7 +32,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx extends ApiRoute with BroadcastRoute { override val route = pathPrefix("contract") { - register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData + register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData ~ addressLimit } @Path("/register") @@ -284,10 +285,62 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx } } + @Path("/contractId/{contractId}/limit/{limit}") + @ApiOperation(value = "Contract Id", + notes = "Get list of transactions where specified contract id has been involved", httpMethod = "GET") + @ApiImplicitParams(Array( + new ApiImplicitParam(name = "contractId", + value = "Contract Id", required = true, dataType = "string", paramType = "path"), + new ApiImplicitParam(name = "limit", + value = "Specified number of records to be returned", + required = true, dataType = "integer", paramType = "path") + )) + def addressLimit: Route = (pathPrefix("contractId") & get) { + pathPrefix(Segment) { address => + Account.fromString(address) match { + case Left(e) => complete(ApiError.fromValidationError(e)) + case Right(a) => + pathPrefix("limit") { + pathEndOrSingleSlash { + complete(invalidLimit) + } ~ + path(Segment) { limitStr => + Exception.allCatch.opt(limitStr.toInt) match { + case Some(limit) if limit > 0 && limit <= MaxTransactionsPerRequest => + complete(Json.arr(JsArray(state.accountTransactions(a, limit, 0)._2.map { case (h, tx) => + processedTxToExtendedJson(tx) + ("height" -> JsNumber(h)) + }))) + case Some(limit) if limit > MaxTransactionsPerRequest => + complete(TooBigArrayAllocation) + case _ => + complete(invalidLimit) + } + } + } ~ complete(StatusCodes.NotFound) + } + } + } + + private def processedTxToExtendedJson(tx: ProcessedTransaction): JsObject = { + tx.transaction match { + case leaseCancel: LeaseCancelTransaction => + tx.json ++ Json.obj( + "lease" -> state.findTransaction[LeaseTransaction]( + leaseCancel.leaseId).map(_.json).getOrElse[JsValue](JsNull)) + case lease: LeaseTransaction => + tx.json ++ Json.obj("leaseStatus" -> (if (state.isLeaseActive(lease)) "active" else "canceled")) + case _ => tx.json + } + } + + private val invalidLimit = StatusCodes.BadRequest -> Json.obj("message" -> "invalid.limit") + } object ContractApiRoute { + val MaxTransactionsPerRequest = 10000 + case class Balance(address: String, confirmations: Int, balance: Long) implicit val balanceFormat: Format[Balance] = Json.format From 67367f25183ebdb75b413bd251e3b3aa4ce734bb Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 27 Jan 2021 16:58:42 +0800 Subject: [PATCH 212/391] add contract tx list api --- src/main/scala/vsys/Application.scala | 2 +- .../api/http/contract/ContractApiRoute.scala | 81 ++++++++++++++++++- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/Application.scala b/src/main/scala/vsys/Application.scala index 4e1e06735..7ed512a44 100644 --- a/src/main/scala/vsys/Application.scala +++ b/src/main/scala/vsys/Application.scala @@ -100,7 +100,7 @@ class Application(val actorSystem: ActorSystem, val settings: VsysSettings) exte LeaseBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels), SPOSApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader), SPOSBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels), - ContractApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader), + ContractApiRoute(settings.restAPISettings, settings.blockchainSettings.stateSettings, wallet, utxStorage, allChannels, time, stateReader), ContractBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels), DbApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader) ) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 8dec37f74..0ef18342f 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -16,7 +16,7 @@ import vsys.blockchain.state.reader.StateReader import vsys.blockchain.transaction._ import vsys.blockchain.UtxPool import vsys.blockchain.contract._ -import vsys.settings.RestAPISettings +import vsys.settings.{RestAPISettings, StateSettings} import vsys.utils.serialization.Deser import vsys.utils.Time import vsys.wallet.Wallet @@ -24,15 +24,22 @@ import vsys.wallet.Wallet import scala.util.Success import scala.util.control.Exception import ContractApiRoute._ +import vsys.blockchain.transaction.TransactionParser.TransactionType import vsys.blockchain.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} @Path("/contract") @Api(value = "/contract") -case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: UtxPool, allChannels: ChannelGroup, time: Time, state: StateReader) +case class ContractApiRoute (settings: RestAPISettings, + stateSettings: StateSettings, + wallet: Wallet, + utx: UtxPool, + allChannels: ChannelGroup, + time: Time, + state: StateReader) extends ApiRoute with BroadcastRoute { override val route = pathPrefix("contract") { - register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData ~ addressLimit + register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData ~ addressLimit ~ transactionList } @Path("/register") @@ -287,7 +294,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx @Path("/contractId/{contractId}/limit/{limit}") @ApiOperation(value = "Contract Id", - notes = "Get list of transactions where specified contract id has been involved", httpMethod = "GET") + notes = "Get list of transactions where specified contract id has been involved, *This is a custom api, you need to enable it in configuration file.*", httpMethod = "GET") @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract Id", required = true, dataType = "string", paramType = "path"), @@ -335,11 +342,77 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx private val invalidLimit = StatusCodes.BadRequest -> Json.obj("message" -> "invalid.limit") + @Path("/list") + @ApiOperation(value = "List", + notes = "Get list of transactions where specified contract id has been involved. *This is a custom api, you need to enable it in configuration file.*", + httpMethod = "GET") + @ApiImplicitParams(Array( + new ApiImplicitParam(name = "contractId", value = "contract id", required = true, dataType = "string", paramType = "query"), + new ApiImplicitParam(name = "txType", value = "transaction type", required = false, dataType = "integer", paramType = "query"), + new ApiImplicitParam(name = "limit", value = "Specified number of records to be returned", required = true, dataType = "integer", paramType = "query"), + new ApiImplicitParam(name = "offset", value = "Specified number of records offset", required = false, dataType = "integer", paramType = "query") + )) + def transactionList: Route = (path("list") & get) { + parameters(('contractId, 'txType.?, 'limit, 'offset ? "0")) { (addressStr, txTypeStrOpt, limitStr, offsetStr) => + Account.fromString(addressStr) match { + case Left(e) => complete(ApiError.fromValidationError(e)) + case Right(a) => + Exception.allCatch.opt(limitStr.toInt) match { + case Some(limit) if limit > 0 && limit <= MaxTransactionsPerRequest => + Exception.allCatch.opt(offsetStr.toInt) match { + case Some(offset) if offset >= 0 && offset <= MaxTransactionOffset => + txTypeStrOpt match { + case None => + complete(txListWrapper(state.accountTransactions(a, limit, offset))) + case Some(txTypeStr) => + Exception.allCatch.opt(TransactionType(txTypeStr.toInt)) match { + case Some(txType: TransactionType.Value) => + if(stateSettings.txTypeAccountTxIds){ + complete(txListWrapper(state.txTypeAccountTransactions(txType, a, limit, offset))) + } + else { + complete(unsupportedStateError("tx-type-account-tx-ids")) + } + case _ => complete(invalidTxType) + } + } + case _ => + complete(invalidOffset) + } + case Some(limit) if limit > MaxTransactionsPerRequest => + complete(TooBigArrayAllocation) + case _ => + complete(invalidLimit) + } + } + } + } + + private def txListWrapper(resFromReader: (Int, Seq[(Int, _ <: ProcessedTransaction)])): JsObject = { + Json.obj( + "totalCount" -> resFromReader._1, + "size" -> resFromReader._2.size, + "transactions" -> resFromReader._2.map { case (h, tx) => + processedTxToExtendedJson(tx) + ("height" -> JsNumber(h)) + } + ) + } + + private def unsupportedStateError(stateName: String) = { + StatusCodes.BadRequest -> Json.obj( + "message" -> s"State $stateName is not enabled at this node. You can turn on the state by editing configuration file.") + } + + private val invalidTxType = StatusCodes.BadRequest -> Json.obj("message" -> "invalid.txType") + + private val invalidOffset = StatusCodes.BadRequest -> Json.obj("message" -> "invalid.offset") + } object ContractApiRoute { val MaxTransactionsPerRequest = 10000 + val MaxTransactionOffset = 10000000 case class Balance(address: String, confirmations: Int, balance: Long) From 3f7f9d8d13fdbf820c27b4a177af4e1dc449eb3c Mon Sep 17 00:00:00 2001 From: Icermli Date: Fri, 29 Jan 2021 13:59:40 +0800 Subject: [PATCH 213/391] delete contract tx related api --- src/main/scala/vsys/Application.scala | 2 +- .../vsys/api/http/TransactionsApiRoute.scala | 2 +- .../api/http/contract/ContractApiRoute.scala | 128 +----------------- 3 files changed, 5 insertions(+), 127 deletions(-) diff --git a/src/main/scala/vsys/Application.scala b/src/main/scala/vsys/Application.scala index 7ed512a44..4e1e06735 100644 --- a/src/main/scala/vsys/Application.scala +++ b/src/main/scala/vsys/Application.scala @@ -100,7 +100,7 @@ class Application(val actorSystem: ActorSystem, val settings: VsysSettings) exte LeaseBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels), SPOSApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader), SPOSBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels), - ContractApiRoute(settings.restAPISettings, settings.blockchainSettings.stateSettings, wallet, utxStorage, allChannels, time, stateReader), + ContractApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader), ContractBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels), DbApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader) ) diff --git a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala index a02017d42..928a60656 100644 --- a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala +++ b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala @@ -54,7 +54,7 @@ case class TransactionsApiRoute( )) def transactionCount: Route = (path("count") & get) { parameters(('address, 'txType.?)) { (addressStr, txTypeStrOpt) => - Address.fromString(addressStr) match { + Account.fromString(addressStr) match { case Left(e) => complete(ApiError.fromValidationError(e)) case Right(a) => txTypeStrOpt match { diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 0ef18342f..b9f7fa3fb 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -7,7 +7,7 @@ import akka.http.scaladsl.server.Route import com.google.common.primitives.Ints import io.netty.channel.group.ChannelGroup import io.swagger.annotations._ -import play.api.libs.json.{Format, JsArray, JsNull, JsNumber, JsObject, JsValue, Json} +import play.api.libs.json.{Format, JsArray, JsNumber, JsObject, Json} import vsys.account.{Account, ContractAccount} import vsys.account.ContractAccount.{contractIdFromBytes, tokenIdFromBytes} import vsys.api.http._ @@ -16,7 +16,7 @@ import vsys.blockchain.state.reader.StateReader import vsys.blockchain.transaction._ import vsys.blockchain.UtxPool import vsys.blockchain.contract._ -import vsys.settings.{RestAPISettings, StateSettings} +import vsys.settings.RestAPISettings import vsys.utils.serialization.Deser import vsys.utils.Time import vsys.wallet.Wallet @@ -24,13 +24,10 @@ import vsys.wallet.Wallet import scala.util.Success import scala.util.control.Exception import ContractApiRoute._ -import vsys.blockchain.transaction.TransactionParser.TransactionType -import vsys.blockchain.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} @Path("/contract") @Api(value = "/contract") case class ContractApiRoute (settings: RestAPISettings, - stateSettings: StateSettings, wallet: Wallet, utx: UtxPool, allChannels: ChannelGroup, @@ -39,7 +36,7 @@ case class ContractApiRoute (settings: RestAPISettings, extends ApiRoute with BroadcastRoute { override val route = pathPrefix("contract") { - register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData ~ addressLimit ~ transactionList + register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData } @Path("/register") @@ -291,129 +288,10 @@ case class ContractApiRoute (settings: RestAPISettings, } } } - - @Path("/contractId/{contractId}/limit/{limit}") - @ApiOperation(value = "Contract Id", - notes = "Get list of transactions where specified contract id has been involved, *This is a custom api, you need to enable it in configuration file.*", httpMethod = "GET") - @ApiImplicitParams(Array( - new ApiImplicitParam(name = "contractId", - value = "Contract Id", required = true, dataType = "string", paramType = "path"), - new ApiImplicitParam(name = "limit", - value = "Specified number of records to be returned", - required = true, dataType = "integer", paramType = "path") - )) - def addressLimit: Route = (pathPrefix("contractId") & get) { - pathPrefix(Segment) { address => - Account.fromString(address) match { - case Left(e) => complete(ApiError.fromValidationError(e)) - case Right(a) => - pathPrefix("limit") { - pathEndOrSingleSlash { - complete(invalidLimit) - } ~ - path(Segment) { limitStr => - Exception.allCatch.opt(limitStr.toInt) match { - case Some(limit) if limit > 0 && limit <= MaxTransactionsPerRequest => - complete(Json.arr(JsArray(state.accountTransactions(a, limit, 0)._2.map { case (h, tx) => - processedTxToExtendedJson(tx) + ("height" -> JsNumber(h)) - }))) - case Some(limit) if limit > MaxTransactionsPerRequest => - complete(TooBigArrayAllocation) - case _ => - complete(invalidLimit) - } - } - } ~ complete(StatusCodes.NotFound) - } - } - } - - private def processedTxToExtendedJson(tx: ProcessedTransaction): JsObject = { - tx.transaction match { - case leaseCancel: LeaseCancelTransaction => - tx.json ++ Json.obj( - "lease" -> state.findTransaction[LeaseTransaction]( - leaseCancel.leaseId).map(_.json).getOrElse[JsValue](JsNull)) - case lease: LeaseTransaction => - tx.json ++ Json.obj("leaseStatus" -> (if (state.isLeaseActive(lease)) "active" else "canceled")) - case _ => tx.json - } - } - - private val invalidLimit = StatusCodes.BadRequest -> Json.obj("message" -> "invalid.limit") - - @Path("/list") - @ApiOperation(value = "List", - notes = "Get list of transactions where specified contract id has been involved. *This is a custom api, you need to enable it in configuration file.*", - httpMethod = "GET") - @ApiImplicitParams(Array( - new ApiImplicitParam(name = "contractId", value = "contract id", required = true, dataType = "string", paramType = "query"), - new ApiImplicitParam(name = "txType", value = "transaction type", required = false, dataType = "integer", paramType = "query"), - new ApiImplicitParam(name = "limit", value = "Specified number of records to be returned", required = true, dataType = "integer", paramType = "query"), - new ApiImplicitParam(name = "offset", value = "Specified number of records offset", required = false, dataType = "integer", paramType = "query") - )) - def transactionList: Route = (path("list") & get) { - parameters(('contractId, 'txType.?, 'limit, 'offset ? "0")) { (addressStr, txTypeStrOpt, limitStr, offsetStr) => - Account.fromString(addressStr) match { - case Left(e) => complete(ApiError.fromValidationError(e)) - case Right(a) => - Exception.allCatch.opt(limitStr.toInt) match { - case Some(limit) if limit > 0 && limit <= MaxTransactionsPerRequest => - Exception.allCatch.opt(offsetStr.toInt) match { - case Some(offset) if offset >= 0 && offset <= MaxTransactionOffset => - txTypeStrOpt match { - case None => - complete(txListWrapper(state.accountTransactions(a, limit, offset))) - case Some(txTypeStr) => - Exception.allCatch.opt(TransactionType(txTypeStr.toInt)) match { - case Some(txType: TransactionType.Value) => - if(stateSettings.txTypeAccountTxIds){ - complete(txListWrapper(state.txTypeAccountTransactions(txType, a, limit, offset))) - } - else { - complete(unsupportedStateError("tx-type-account-tx-ids")) - } - case _ => complete(invalidTxType) - } - } - case _ => - complete(invalidOffset) - } - case Some(limit) if limit > MaxTransactionsPerRequest => - complete(TooBigArrayAllocation) - case _ => - complete(invalidLimit) - } - } - } - } - - private def txListWrapper(resFromReader: (Int, Seq[(Int, _ <: ProcessedTransaction)])): JsObject = { - Json.obj( - "totalCount" -> resFromReader._1, - "size" -> resFromReader._2.size, - "transactions" -> resFromReader._2.map { case (h, tx) => - processedTxToExtendedJson(tx) + ("height" -> JsNumber(h)) - } - ) - } - - private def unsupportedStateError(stateName: String) = { - StatusCodes.BadRequest -> Json.obj( - "message" -> s"State $stateName is not enabled at this node. You can turn on the state by editing configuration file.") - } - - private val invalidTxType = StatusCodes.BadRequest -> Json.obj("message" -> "invalid.txType") - - private val invalidOffset = StatusCodes.BadRequest -> Json.obj("message" -> "invalid.offset") - } object ContractApiRoute { - val MaxTransactionsPerRequest = 10000 - val MaxTransactionOffset = 10000000 - case class Balance(address: String, confirmations: Int, balance: Long) implicit val balanceFormat: Format[Balance] = Json.format From 1c5f96a6b180b05b1a18604dd8fc9571a0e9546e Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 29 Jan 2021 15:31:15 +0800 Subject: [PATCH 214/391] update last token index api --- .../api/http/contract/ContractApiRoute.scala | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 9ddb43e0b..14527d420 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -77,11 +77,18 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx )) def lastToken: Route = (get & path("lastTokenIndex" / Segment)) { contractId => ByteStr.decodeBase58(contractId) match { - case Success(id) => complete(Json.obj( - "contractId" -> contractId, - "lastTokenIndex" -> state.contractTokens(id) - )) - case _ => complete(InvalidAddress) + case Success(id) if ContractAccount.fromString(contractId).isRight => { + val lastTokenIndex = state.contractTokens(id) - 1 + if (lastTokenIndex == -1) { + complete(CustomValidationError("No token generated in this contract")) + } else { + complete(Json.obj( + "contractId" -> contractId, + "lastTokenIndex" -> lastTokenIndex + )) + } + } + case _ => complete(InvalidContractAddress) } } From a0888afc2741479cae11acd9cfc99dbd434c512f Mon Sep 17 00:00:00 2001 From: Julianxa Date: Sun, 31 Jan 2021 23:53:58 +0800 Subject: [PATCH 215/391] Improvement of address API descriptions and examples --- .../api/http/addresses/AddressApiRoute.scala | 60 +++++++++++++------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/main/scala/vsys/api/http/addresses/AddressApiRoute.scala b/src/main/scala/vsys/api/http/addresses/AddressApiRoute.scala index f9056f179..1ae16ad58 100644 --- a/src/main/scala/vsys/api/http/addresses/AddressApiRoute.scala +++ b/src/main/scala/vsys/api/http/addresses/AddressApiRoute.scala @@ -32,8 +32,11 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } ~ root ~ create @Path("/{address}") - @ApiOperation(value = "Delete", notes = "Remove the account with address {address} from the wallet", httpMethod = "DELETE", + @ApiOperation(value = "Delete", notes = "Remove the `address` from the wallet", httpMethod = "DELETE", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @@ -50,14 +53,14 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/sign/{address}") - @ApiOperation(value = "Sign", notes = "Sign a message with a private key associated with {address}", httpMethod = "POST", + @ApiOperation(value = "Sign", notes = "Sign a `message` with a private key associated with an `address`", httpMethod = "POST", authorizations = Array(new Authorization("api_key"))) @ApiImplicitParams(Array( new ApiImplicitParam(name = "message", value = "Message to sign as a plain string", required = true, paramType = "body", dataType = "string"), new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with error or json like {\"message\": \"Base58-encoded\",\"publickey\": \"Base58-encoded\", \"signature\": \"Base58-encoded\"}") + new ApiResponse(code = 200, message = "Successful Operation") )) def sign: Route = { path("sign" / Segment) { address => @@ -66,14 +69,14 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/signText/{address}") - @ApiOperation(value = "Sign", notes = "Sign a message with a private key associated with {address}", httpMethod = "POST", + @ApiOperation(value = "Sign", notes = "Sign a message with a private key associated with `address`", httpMethod = "POST", authorizations = Array(new Authorization("api_key"))) @ApiImplicitParams(Array( new ApiImplicitParam(name = "message", value = "Message to sign as a plain string", required = true, paramType = "body", dataType = "string"), new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with error or json like {\"message\": \"plain text\",\"publickey\": \"Base58-encoded\", \"signature\": \"Base58-encoded\"}") + new ApiResponse(code = 200, message = "Successful Operation") )) def signText: Route = { path("signText" / Segment) { address => @@ -82,8 +85,11 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/verify/{address}") - @ApiOperation(value = "Verify", notes = "Check a signature of a message signed by an account", httpMethod = "POST", + @ApiOperation(value = "Verify", notes = "Check a signature of a base58-encoded message(`body`) signed by an `address`", httpMethod = "POST", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam( @@ -102,8 +108,11 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/verifyText/{address}") - @ApiOperation(value = "Verify text", notes = "Check a signature of a message signed by an account", httpMethod = "POST", + @ApiOperation(value = "Verify text", notes = "Check a signature of a plain message(`body`) signed by an `address`", httpMethod = "POST", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam( @@ -120,7 +129,7 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/balance/{address}") - @ApiOperation(value = "Balance", notes = "Account's balance", httpMethod = "GET") + @ApiOperation(value = "Balance", notes = "Get the available balance of a specified `address`", httpMethod = "GET", response = classOf[Balance]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @@ -129,7 +138,7 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/balance/details/{address}") - @ApiOperation(value = "Details for balance", notes = "Account's balances", httpMethod = "GET") + @ApiOperation(value = "Details for balance", notes = "Get the balance details of a specified `address` including **effective, mintingAverage and available balance**.", httpMethod = "GET", response = classOf[BalanceDetails]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @@ -140,7 +149,7 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/balance/{address}/{confirmations}") - @ApiOperation(value = "Confirmed balance", notes = "Balance of {address} after {confirmations}", httpMethod = "GET") + @ApiOperation(value = "Confirmed balance", notes = "Get the balance of an `address` after `confirmations`", httpMethod = "GET", response = classOf[Balance]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "confirmations", value = "0", required = true, dataType = "integer", paramType = "path") @@ -153,7 +162,7 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta @Path("/effectiveBalance/{address}") - @ApiOperation(value = "Balance", notes = "Account's balance", httpMethod = "GET") + @ApiOperation(value = "Balance", notes = "Get the effective balance of a specified `address`", httpMethod = "GET", response = classOf[Balance]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @@ -164,7 +173,7 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/effectiveBalance/{address}/{confirmations}") - @ApiOperation(value = "Confirmed balance", notes = "Balance of {address} after {confirmations}", httpMethod = "GET") + @ApiOperation(value = "Confirmed balance", notes = "Get the balance of an `address` after `confirmations`", httpMethod = "GET", response = classOf[Balance]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "confirmations", value = "0", required = true, dataType = "integer", paramType = "path") @@ -178,8 +187,11 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/seed/{address}") - @ApiOperation(value = "Seed", notes = "Export seed value for the {address}", httpMethod = "GET", + @ApiOperation(value = "Seed", notes = "Export seed value for the `address`", httpMethod = "GET", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of a seed or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @@ -194,7 +206,7 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/validate/{address}") - @ApiOperation(value = "Validate", notes = "Check whether address {address} is valid or not", httpMethod = "GET") + @ApiOperation(value = "Validate", notes = "Check whether `address` is valid or not", httpMethod = "GET", response = classOf[Validity]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @@ -203,6 +215,9 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of a addresses list or error") + )) @ApiOperation(value = "Addresses", notes = "Get wallet accounts addresses", httpMethod = "GET") def root: Route = (path("addresses") & get) { val accounts = wallet.privateKeyAccounts @@ -211,10 +226,13 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/seq/{from}/{to}") - @ApiOperation(value = "Seq", notes = "Get wallet accounts addresses", httpMethod = "GET") + @ApiOperation(value = "Seq", notes = "Get wallet accounts addresses by specified a start nonce index(`from`) and a end nonce index(`to`)", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of wallet addresses or error") + )) @ApiImplicitParams(Array( - new ApiImplicitParam(name = "from", value = "Start address", required = true, dataType = "integer", paramType = "path"), - new ApiImplicitParam(name = "to", value = "address", required = true, dataType = "integer", paramType = "path") + new ApiImplicitParam(name = "from", value = "nonce start index", required = true, dataType = "integer", paramType = "path"), + new ApiImplicitParam(name = "to", value = "nonce end index", required = true, dataType = "integer", paramType = "path") )) def seq: Route = { (path("seq" / IntNumber / IntNumber) & get) { case (start, end) => @@ -229,6 +247,9 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta } @Path("/") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) @ApiOperation(value = "Create", notes = "Create a new account in the wallet(if it exists)", httpMethod = "POST", authorizations = Array(new Authorization("api_key"))) def create: Route = (path("addresses") & post) { @@ -318,7 +339,10 @@ case class AddressApiRoute(settings: RestAPISettings, wallet: Wallet, state: Sta new ApiImplicitParam(name = "publicKey", value = "Public key Base58-encoded", required = true, paramType = "path", dataType = "string") )) - @ApiOperation(value = "Address from Public Key", notes = "Generate a address from public key", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of an address or error") + )) + @ApiOperation(value = "Address from Public Key", notes = "Generate an address from a `publicKey`", httpMethod = "GET") def publicKey: Route = (path("publicKey" / Segment) & get) { publicKey => Base58.decode(publicKey) match { case Success(pubKeyBytes) => { From be7f034da87660070e0b65fb8358b0c788a50399 Mon Sep 17 00:00:00 2001 From: Julianxa Date: Sun, 31 Jan 2021 23:55:32 +0800 Subject: [PATCH 216/391] Improvement of contract API descriptions and examples --- .../api/http/contract/ContractApiRoute.scala | 65 ++++++++++--------- .../contract/ContractBroadcastApiRoute.scala | 10 ++- ...SignedExecuteContractFunctionRequest.scala | 4 +- .../SignedRegisterContractRequest.scala | 4 +- 4 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 9ddb43e0b..6c9b10b68 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -31,7 +31,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx extends ApiRoute with BroadcastRoute { override val route = pathPrefix("contract") { - register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData ~ lastToken + register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData } @Path("/register") @@ -47,14 +47,13 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx required = true, paramType = "body", dataType = "vsys.api.http.contract.RegisterContractRequest", - defaultValue = "{\n\t\"sender\": \"3Mx2afTZ2KbRrLNbytyzTtXukZvqEB8SkW7\",\n\t\"contract\": \"contract\",\n\t\"data\":\"data\",\n\t\"description\":\"5VECG3ZHwy\",\n\t\"fee\": 100000,\n\t\"feeScale\": 100\n}" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def register: Route = processRequest("register", (t: RegisterContractRequest) => doBroadcast(TransactionFactory.registerContract(t, wallet, time))) @Path("/vBalance/{contractId}") - @ApiOperation(value = "Contract balance", notes = "Get contract account v balance associated with contract id.", httpMethod = "GET") + @ApiOperation(value = "Contract balance", notes = "Get contract account **v balance** associated with `contractId`.", httpMethod = "GET", response = classOf[Balance]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract ID", required = true, dataType = "string", paramType = "path") )) @@ -70,23 +69,11 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx ))).getOrElse(InvalidContractAddress) } - @Path("/lastTokenIndex/{contractId}") - @ApiOperation(value = "Last Token Index", notes = "Token contract last token index", httpMethod = "Get") - @ApiImplicitParams(Array( - new ApiImplicitParam(name = "contractId", value = "Contract ID", required = true, dataType = "string", paramType = "path") - )) - def lastToken: Route = (get & path("lastTokenIndex" / Segment)) { contractId => - ByteStr.decodeBase58(contractId) match { - case Success(id) => complete(Json.obj( - "contractId" -> contractId, - "lastTokenIndex" -> state.contractTokens(id) - )) - case _ => complete(InvalidAddress) - } - } - @Path("/content/{contractId}") - @ApiOperation(value = "Contract content", notes = "Get contract content associated with a contract id.", httpMethod = "GET") + @ApiOperation(value = "Contract content", notes = "Get **contract content** associated with a `contractId`.", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the contract content or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract ID", required = true, dataType = "string", paramType = "path") )) @@ -101,18 +88,24 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx } } - @Path("/data/{contractId}/{key}") - @ApiOperation(value = "Contract Data", notes = "Contract data by given contract ID and key (default numerical 0).", httpMethod = "Get") + @Path("data/{contractId}/{key}") + @ApiOperation(value = "Contract Data", notes = "Get **contract data** by given `contractId` and `key` (default numerical 0).", httpMethod = "Get", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of contract data or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract Account", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "key", value = "Key", required = true, dataType = "string", paramType = "path") )) - def getContractData: Route = (get & path("data" / Segment / Segment)) { (contractId, key) => + def getContractData: Route = (get & withAuth & path("data" / Segment / Segment)) { (contractId, key) => complete(dataJson(contractId, key)) } @Path("/info/{contractId}") - @ApiOperation(value = "Info", notes = "Get contract info associated with a contract id.", httpMethod = "GET") + @ApiOperation(value = "Info", notes = "Get **contract info** associated with a `contractId`.", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the contract info or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract ID", required = true, dataType = "string", paramType = "path") )) @@ -158,7 +151,10 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx } @Path("/tokenInfo/{tokenId}") - @ApiOperation(value = "Token's Info", notes = "Token's info by given token", httpMethod = "Get") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of token info or error") + )) + @ApiOperation(value = "Token's Info", notes = "Get the **token's info** by given `tokenId`", httpMethod = "Get") @ApiImplicitParams(Array( new ApiImplicitParam(name = "tokenId", value = "Token ID", required = true, dataType = "string", paramType = "path") )) @@ -193,8 +189,11 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx } } - @Path("/balance/{address}/{tokenId}") - @ApiOperation(value = "Token's balance", notes = "Account's balance by given token", httpMethod = "Get") + @Path("balance/{address}/{tokenId}") + @ApiOperation(value = "Token's balance", notes = "Get the **balance** of a specified `tokenId` by a given `address`", httpMethod = "Get") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the token balance or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "tokenId", value = "Token ID", required = true, dataType = "string", paramType = "path") @@ -261,15 +260,17 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.contract.ExecuteContractFunctionRequest", - defaultValue = "{\n\t\"sender\": \"3Mx2afTZ2KbRrLNbytyzTtXukZvqEB8SkW7\",\n\t\"contractId\": \"contractId\",\n\t\"funcIdx\": \"0\",\n\t\"data\":\"data\",\n\t\"description\":\"5VECG3ZHwy\",\n\t\"fee\": 100000,\n\t\"feeScale\": 100\n}" + dataType = "vsys.api.http.contract.ExecuteContractFunctionRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def execute: Route = processRequest("execute", (t: ExecuteContractFunctionRequest) => doBroadcast(TransactionFactory.executeContractFunction(t, wallet, time))) - @Path("/contractId/{contractId}/tokenIndex/{tokenIndex}") - @ApiOperation(value = "Token's Id", notes = "Token Id from contract Id and token index", httpMethod = "Get") + @Path("contractId/{contractId}/tokenIndex/{tokenIndex}") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of a token id or error") + )) + @ApiOperation(value = "Token's Id", notes = "Get the **token Id** from the specified `contractId` and `tokenIndex`", httpMethod = "Get") @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract ID", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "tokenIndex", value = "Token Index", required = true, dataType = "integer", paramType = "path") diff --git a/src/main/scala/vsys/api/http/contract/ContractBroadcastApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractBroadcastApiRoute.scala index a371c517f..6da8aa578 100644 --- a/src/main/scala/vsys/api/http/contract/ContractBroadcastApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractBroadcastApiRoute.scala @@ -30,11 +30,10 @@ case class ContractBroadcastApiRoute(settings: RestAPISettings, value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.contract.SignedRegisterContractRequest", - defaultValue = "{\n\t\"contract\": \"contract\",\n\t\"data\":\"data\",\n\t\"description\":\"5VECG3ZHwy\",\n\t\"senderPublicKey\": \"11111\",\n\t\"fee\": 100000,\n\t\"feeScale\": 100,\"timestamp\": 12345678,\n\t\"signature\": \"asdasdasd\"\n}" + dataType = "vsys.api.http.contract.SignedRegisterContractRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def signedRegister: Route = (path("register") & post) { json[SignedRegisterContractRequest] { contractReq => doBroadcast(contractReq.toTx) @@ -52,11 +51,10 @@ case class ContractBroadcastApiRoute(settings: RestAPISettings, value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.contract.SignedExecuteContractFunctionRequest", - defaultValue = "{\n\t\"contractId\": \"contractId\",\n\t\"funcIdx\": \"0\",\n\t\"data\":\"data\",\n\t\"description\":\"5VECG3ZHwy\",\n\t\"senderPublicKey\": \"11111\",\n\t\"fee\": 100000,\n\t\"feeScale\": 100,\"timestamp\": 12345678,\n\t\"signature\": \"asdasdasd\"\n}" + dataType = "vsys.api.http.contract.SignedExecuteContractFunctionRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def signedExecute: Route = (path("execute") & post) { json[SignedExecuteContractFunctionRequest] { contractReq => doBroadcast(contractReq.toTx) diff --git a/src/main/scala/vsys/api/http/contract/SignedExecuteContractFunctionRequest.scala b/src/main/scala/vsys/api/http/contract/SignedExecuteContractFunctionRequest.scala index 86444d318..4d0a6a21e 100644 --- a/src/main/scala/vsys/api/http/contract/SignedExecuteContractFunctionRequest.scala +++ b/src/main/scala/vsys/api/http/contract/SignedExecuteContractFunctionRequest.scala @@ -21,9 +21,9 @@ case class SignedExecuteContractFunctionRequest(@ApiModelProperty(value = "Base5 functionData: String, @ApiModelProperty(value = "Base58 encoded attachment") attachment: Option[String], - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "30000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short, @ApiModelProperty(required = true) timestamp: Long, diff --git a/src/main/scala/vsys/api/http/contract/SignedRegisterContractRequest.scala b/src/main/scala/vsys/api/http/contract/SignedRegisterContractRequest.scala index 0588d57a0..0b25b515c 100644 --- a/src/main/scala/vsys/api/http/contract/SignedRegisterContractRequest.scala +++ b/src/main/scala/vsys/api/http/contract/SignedRegisterContractRequest.scala @@ -19,9 +19,9 @@ case class SignedRegisterContractRequest(@ApiModelProperty(value = "Base58 encod initData: String, @ApiModelProperty(value = "Description of contract") description: Option[String], - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "10000000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short, @ApiModelProperty(required = true) timestamp: Long, From a91d760f236caccfbfb1f6e1fd3d51e719f78f0b Mon Sep 17 00:00:00 2001 From: twwu123 Date: Mon, 1 Feb 2021 10:46:30 +0800 Subject: [PATCH 217/391] Fix V Stable Swap indexes --- .../blockchain/contract/ContractVStableSwap.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index cc728fe43..4ec07dc35 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -110,9 +110,9 @@ object ContractVStableSwap { cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(11.toByte), + ), DataType.OpcBlock).bytes ++ Array(9.toByte), conditionIf ++ Array(6.toByte, 7.toByte), - conditionIf ++ Array(8.toByte, 10.toByte), + conditionIf ++ Array(8.toByte, 9.toByte), assertTrue ++ Array(5.toByte) ) lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) @@ -142,9 +142,9 @@ object ContractVStableSwap { cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(11.toByte), + ), DataType.OpcBlock).bytes ++ Array(9.toByte), conditionIf ++ Array(6.toByte, 7.toByte), - conditionIf ++ Array(8.toByte, 10.toByte), + conditionIf ++ Array(8.toByte, 9.toByte), assertTrue ++ Array(5.toByte) ) lazy val withdrawTrigger: Array[Byte] = getFunctionBytes(withdrawId, onWithDrawTriggerType, nonReturnType, withdrawDataType, withdrawTriggerOpcs) @@ -176,8 +176,8 @@ object ContractVStableSwap { compareGreater ++ Array(11.toByte, 12.toByte, 13.toByte), assertTrue ++ Array(13.toByte), loadTransactionId ++ Array(14.toByte), - cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 9.toByte), - cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 10.toByte), + cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 10.toByte, 8.toByte), + cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 10.toByte, 9.toByte), cdbvMapSet ++ Array(orderOwnerMap.index, 14.toByte, 10.toByte), cdbvMapSet ++ Array(feeBaseMap.index, 14.toByte, 0.toByte), cdbvMapSet ++ Array(feeTargetMap.index, 14.toByte, 1.toByte), From a3224398089ce48ab6fb4e7be5097c4695114eac Mon Sep 17 00:00:00 2001 From: Julianxa Date: Mon, 1 Feb 2021 13:37:52 +0800 Subject: [PATCH 218/391] Improvement of database API descriptions and examples --- .../scala/vsys/api/http/database/DbApiRoute.scala | 11 ++++++----- .../vsys/api/http/database/SignedDbPutRequest.scala | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/api/http/database/DbApiRoute.scala b/src/main/scala/vsys/api/http/database/DbApiRoute.scala index 94e5b621f..53509fe83 100644 --- a/src/main/scala/vsys/api/http/database/DbApiRoute.scala +++ b/src/main/scala/vsys/api/http/database/DbApiRoute.scala @@ -39,10 +39,9 @@ case class DbApiRoute (settings: RestAPISettings, wallet: Wallet, utx: UtxPool, required = true, paramType = "body", dataType = "vsys.api.http.database.DbPutRequest", - defaultValue = "{\n\t\"dbKey\": \"name\",\n\t\"data\": \"dbdata\",\n\t\"dataType\": \"ByteArray\",\n\t\"sender\": \"3Mx2afTZ2KbRrLNbytyzTtXukZvqEB8SkW7\",\n\t\"fee\": 100000,\n\t\"feeScale\": 100\n}" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def putKV: Route = processRequest("put", (t: DbPutRequest) => doBroadcast(TransactionFactory.dbPut(t, wallet, time))) @Path("/broadcast/put") @@ -57,10 +56,9 @@ case class DbApiRoute (settings: RestAPISettings, wallet: Wallet, utx: UtxPool, required = true, paramType = "body", dataType = "vsys.api.http.database.SignedDbPutRequest", - defaultValue = "{\n\t\"dbKey\": \"name\",\n\t\"data\": \"dbdata\",\n\t\"dataType\": \"ByteArray\",\n\t\"sender\": \"3Mx2afTZ2KbRrLNbytyzTtXukZvqEB8SkW7\",\n\t\"fee\": 100000,\n\t\"feeScale\": 100\n\t\"timestamp\": 12345678,\n\t\"signature\": \"asdasdasd\"\n}" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def signPutKV: Route = (path("broadcast" / "put") & post) { json[SignedDbPutRequest] { signedDbPutReq => doBroadcast(signedDbPutReq.toTx) @@ -68,7 +66,10 @@ case class DbApiRoute (settings: RestAPISettings, wallet: Wallet, utx: UtxPool, } @Path("/get/{nameSpace}/{dbKey}") - @ApiOperation(value = "get", notes = "Get db entry", httpMethod = "GET") + @ApiOperation(value = "get", notes = "Get **db entries** by given `nameSpace` and `dbKey`", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of db entries or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "nameSpace", value = "Address", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "dbKey", value = "dbKey", required = true, dataType = "string", paramType = "path") diff --git a/src/main/scala/vsys/api/http/database/SignedDbPutRequest.scala b/src/main/scala/vsys/api/http/database/SignedDbPutRequest.scala index 9e18e7b75..be54dec37 100644 --- a/src/main/scala/vsys/api/http/database/SignedDbPutRequest.scala +++ b/src/main/scala/vsys/api/http/database/SignedDbPutRequest.scala @@ -16,9 +16,9 @@ case class SignedDbPutRequest(@ApiModelProperty(value = "Base58 encoded sender p dataType: String, @ApiModelProperty(value = "data") data: String, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short, @ApiModelProperty(required = true) timestamp: Long, From c697afe54a9990fa848b844efdf92b471e731d4b Mon Sep 17 00:00:00 2001 From: Julianxa Date: Mon, 1 Feb 2021 14:14:44 +0800 Subject: [PATCH 219/391] Improvement of leasing API descriptions and examples --- .../scala/vsys/api/http/leasing/LeaseApiRoute.scala | 11 ++++++----- .../api/http/leasing/LeaseBroadcastApiRoute.scala | 11 ++++++----- .../api/http/leasing/SignedLeaseCancelRequest.scala | 5 ++--- .../vsys/api/http/leasing/SignedLeaseRequest.scala | 4 ++-- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main/scala/vsys/api/http/leasing/LeaseApiRoute.scala b/src/main/scala/vsys/api/http/leasing/LeaseApiRoute.scala index 01f5aecda..e11d29765 100644 --- a/src/main/scala/vsys/api/http/leasing/LeaseApiRoute.scala +++ b/src/main/scala/vsys/api/http/leasing/LeaseApiRoute.scala @@ -36,14 +36,16 @@ case class LeaseApiRoute(settings: RestAPISettings, wallet: Wallet, utx: UtxPool value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.leasing.LeaseRequest", - defaultValue = "{\n\t\"amount\": 100000000,\n\t\"recipient\": \"3NBsppTVpai9jq6agi9wXXrWhaMPPig48Aw\",\n\t\"sender\": \"3Mx2afTZ2KbRrLNbytyzTtXukZvqEB8SkW7\",\n\t\"fee\": 100000,\n\t\"feeScale\": 100\n}" + dataType = "vsys.api.http.leasing.LeaseRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def lease: Route = processRequest("lease", (t: LeaseRequest) => doBroadcast(TransactionFactory.lease(t, wallet, time))) @Path("/cancel") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) @ApiOperation(value = "Interrupt a lease", httpMethod = "POST", produces = "application/json", @@ -55,8 +57,7 @@ case class LeaseApiRoute(settings: RestAPISettings, wallet: Wallet, utx: UtxPool value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.leasing.LeaseCancelRequest", - defaultValue = "{\n\t\"sender\": \"3Myss6gmMckKYtka3cKCM563TBJofnxvfD7\",\n\t\"txId\": \"ABMZDPY4MyQz7kKNAevw5P9eNmRErMutJoV9UNeCtqRV\",\n\t\"fee\": 10000000,\n\t\"feeScale\": 100\n}" + dataType = "vsys.api.http.leasing.LeaseCancelRequest" ) )) def cancel: Route = processRequest("cancel", (t: LeaseCancelRequest) => doBroadcast(TransactionFactory.leaseCancel(t, wallet, time))) diff --git a/src/main/scala/vsys/api/http/leasing/LeaseBroadcastApiRoute.scala b/src/main/scala/vsys/api/http/leasing/LeaseBroadcastApiRoute.scala index eb04419f3..0dd74b67d 100644 --- a/src/main/scala/vsys/api/http/leasing/LeaseBroadcastApiRoute.scala +++ b/src/main/scala/vsys/api/http/leasing/LeaseBroadcastApiRoute.scala @@ -31,11 +31,10 @@ case class LeaseBroadcastApiRoute( value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.leasing.SignedLeaseRequest", - defaultValue = "{\n\t\"amount\": 100000000,\n\t\"recipient\": \"3NBsppTVpai9jq6agi9wXXrWhaMPPig48Aw\",\n\t\"senderPublicKey\": \"11111\",\n\t\"fee\": 100000,\n\t\"feeScale\": 100,\n\t\"timestamp\": 12345678,\n\t\"signature\": \"asdasdasd\"\n}" + dataType = "vsys.api.http.leasing.SignedLeaseRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def signedLease: Route = (path("lease") & post) { json[SignedLeaseRequest] { leaseReq => doBroadcast(leaseReq.toTx) @@ -47,14 +46,16 @@ case class LeaseBroadcastApiRoute( httpMethod = "POST", produces = "application/json", consumes = "application/json") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) @ApiImplicitParams(Array( new ApiImplicitParam( name = "body", value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.leasing.SignedLeaseCancelRequest", - defaultValue = "{\n\t\"sender\": \"3Myss6gmMckKYtka3cKCM563TBJofnxvfD7\",\n\t\"txId\": \"ABMZDPY4MyQz7kKNAevw5P9eNmRErMutJoV9UNeCtqRV\",\n\t\"fee\": 10000000,\n\t\"feeScale\": 100,\n\t\"timestamp\": 12345678,\n\t\"signature\": \"asdasdasd\"\n}" + dataType = "vsys.api.http.leasing.SignedLeaseCancelRequest" ) )) def signedLeaseCancel: Route = (path("cancel") & post) { diff --git a/src/main/scala/vsys/api/http/leasing/SignedLeaseCancelRequest.scala b/src/main/scala/vsys/api/http/leasing/SignedLeaseCancelRequest.scala index 30825330e..fcf204825 100644 --- a/src/main/scala/vsys/api/http/leasing/SignedLeaseCancelRequest.scala +++ b/src/main/scala/vsys/api/http/leasing/SignedLeaseCancelRequest.scala @@ -16,9 +16,9 @@ case class SignedLeaseCancelRequest(@ApiModelProperty(value = "Base58 encoded se timestamp: Long, @ApiModelProperty(required = true) signature: String, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "10000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short) extends BroadcastRequest { def toTx: Either[ValidationError, LeaseCancelTransaction] = for { _sender <- PublicKeyAccount.fromBase58String(senderPublicKey) @@ -37,4 +37,3 @@ case class SignedLeaseCancelRequest(@ApiModelProperty(value = "Base58 encoded se object SignedLeaseCancelRequest { implicit val leaseCancelRequestFormat: Format[SignedLeaseCancelRequest] = Json.format } - diff --git a/src/main/scala/vsys/api/http/leasing/SignedLeaseRequest.scala b/src/main/scala/vsys/api/http/leasing/SignedLeaseRequest.scala index 1c875941f..ca0ae6787 100644 --- a/src/main/scala/vsys/api/http/leasing/SignedLeaseRequest.scala +++ b/src/main/scala/vsys/api/http/leasing/SignedLeaseRequest.scala @@ -13,9 +13,9 @@ case class SignedLeaseRequest(@ApiModelProperty(value = "Base58 encoded sender p senderPublicKey: String, @ApiModelProperty(required = true) amount: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "10000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short, @ApiModelProperty(value = "Recipient address", required = true) recipient: String, From 943281b6719927087f22d7edeb9cba51a48ac9a2 Mon Sep 17 00:00:00 2001 From: Julianxa Date: Mon, 1 Feb 2021 14:15:00 +0800 Subject: [PATCH 220/391] Improvement of spos API descriptions and examples --- .../vsys/api/http/spos/SPOSApiRoute.scala | 10 +++---- .../api/http/spos/SPOSBroadcastApiRoute.scala | 10 +++---- .../http/spos/SignedContendSlotsRequest.scala | 4 +-- .../http/spos/SignedReleaseSlotsRequest.scala | 6 ++-- .../api/http/spos/SposConsensusApiRoute.scala | 28 ++++++++++++++----- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/main/scala/vsys/api/http/spos/SPOSApiRoute.scala b/src/main/scala/vsys/api/http/spos/SPOSApiRoute.scala index e8d1b3cb6..fc959f6f6 100644 --- a/src/main/scala/vsys/api/http/spos/SPOSApiRoute.scala +++ b/src/main/scala/vsys/api/http/spos/SPOSApiRoute.scala @@ -34,11 +34,10 @@ case class SPOSApiRoute(settings: RestAPISettings, wallet: Wallet, utx: UtxPool, value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.spos.ContendSlotsRequest", - defaultValue = "{\n\t\"slotId\": 0,\n\t\"sender\": \"3N4SMepbKXPRADdjfUwNYKdcZdMoVJGXQP5\",\n\t\"fee\": 10000000\n\t\"feeScale\": 100\n}" + dataType = "vsys.api.http.spos.ContendSlotsRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def contend: Route = processRequest("contend", (t: ContendSlotsRequest) => doBroadcast(TransactionFactory.contendSlots(t, wallet, time))) @Path("/release") @@ -53,11 +52,10 @@ case class SPOSApiRoute(settings: RestAPISettings, wallet: Wallet, utx: UtxPool, value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.spos.ReleaseSlotsRequest", - defaultValue = "{\n\t\"slotId\": 0,\n\t\"sender\": \"3N4SMepbKXPRADdjfUwNYKdcZdMoVJGXQP5\",\n\t\"fee\": 100000\n\t\"feeScale\": 100\n}" + dataType = "vsys.api.http.spos.ReleaseSlotsRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def release: Route = processRequest("release", (t: ReleaseSlotsRequest) => doBroadcast(TransactionFactory.releaseSlots(t, wallet, time))) } diff --git a/src/main/scala/vsys/api/http/spos/SPOSBroadcastApiRoute.scala b/src/main/scala/vsys/api/http/spos/SPOSBroadcastApiRoute.scala index 662dc38b2..31072b4c4 100644 --- a/src/main/scala/vsys/api/http/spos/SPOSBroadcastApiRoute.scala +++ b/src/main/scala/vsys/api/http/spos/SPOSBroadcastApiRoute.scala @@ -31,11 +31,10 @@ case class SPOSBroadcastApiRoute( value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.spos.SignedContendSlotsRequest", - defaultValue = "{\n\t\"slotId\": 0,\n\t\"senderPublicKey\": \"11111\",\n\t\"fee\": 100000\n\t\"feeScale\": 100\n\t\"timestamp\": 12345678,\n\t\"signature\": \"asdasdasd\"\n}" + dataType = "vsys.api.http.spos.SignedContendSlotsRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def signedContend: Route = (path("contend") & post) { json[SignedContendSlotsRequest] { contendReq => doBroadcast(contendReq.toTx) @@ -53,11 +52,10 @@ case class SPOSBroadcastApiRoute( value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.spos.SignedReleaseSlotsRequest", - defaultValue = "{\n\t\"slotId\": 0,\n\t\"senderPublicKey\": \"11111\",\n\t\"fee\": 100000\n\t\"feeScale\": 100\n\t\"timestamp\": 12345678,\n\t\"signature\": \"asdasdasd\"\n}" + dataType = "vsys.api.http.spos.SignedReleaseSlotsRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def signRelease: Route = (path("release") & post) { json[SignedReleaseSlotsRequest] { releaseReq => doBroadcast(releaseReq.toTx) diff --git a/src/main/scala/vsys/api/http/spos/SignedContendSlotsRequest.scala b/src/main/scala/vsys/api/http/spos/SignedContendSlotsRequest.scala index 06aa16725..c3cb70d36 100644 --- a/src/main/scala/vsys/api/http/spos/SignedContendSlotsRequest.scala +++ b/src/main/scala/vsys/api/http/spos/SignedContendSlotsRequest.scala @@ -10,9 +10,9 @@ import vsys.blockchain.transaction.spos.ContendSlotsTransaction case class SignedContendSlotsRequest(@ApiModelProperty(value = "Base58 encoded sender public key", required = true) senderPublicKey: String, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "5000000000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short, @ApiModelProperty(required = true) slotId: Int, diff --git a/src/main/scala/vsys/api/http/spos/SignedReleaseSlotsRequest.scala b/src/main/scala/vsys/api/http/spos/SignedReleaseSlotsRequest.scala index 78de5c617..7277c0667 100644 --- a/src/main/scala/vsys/api/http/spos/SignedReleaseSlotsRequest.scala +++ b/src/main/scala/vsys/api/http/spos/SignedReleaseSlotsRequest.scala @@ -10,11 +10,11 @@ import vsys.blockchain.transaction.spos.ReleaseSlotsTransaction case class SignedReleaseSlotsRequest(@ApiModelProperty(value = "Base58 encoded sender public key", required = true) senderPublicKey: String, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "10000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "0") slotId: Int, @ApiModelProperty(required = true) timestamp: Long, diff --git a/src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala b/src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala index 8dd3ad042..93fbf4d59 100755 --- a/src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala +++ b/src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala @@ -25,10 +25,13 @@ case class SposConsensusApiRoute( } @Path("/generatingBalance/{address}") - @ApiOperation(value = "Generating balance", notes = "Account's generating balance(the same as balance atm)", httpMethod = "GET") + @ApiOperation(value = "Generating balance", notes = "Get Account's generating balance(the same as balance atm)", httpMethod = "GET") @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json with error or response like {\"address\": \"your address\",\"balance\": \"your balance\"}") + )) def generatingBalance: Route = (path("generatingBalance" / Segment) & get) { address => Address.fromString(address) match { case Left(_) => complete(InvalidAddress) @@ -40,7 +43,10 @@ case class SposConsensusApiRoute( } @Path("/mintingAverageBalance/{address}") - @ApiOperation(value = "Minting average balance", notes = "Account's minting average balance", httpMethod = "GET") + @ApiOperation(value = "Minting average balance", notes = "Get the **minting average balance**(MAB) of an `address`", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of an address's MAB or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Address", required = true, dataType = "string", paramType = "path") )) @@ -56,7 +62,9 @@ case class SposConsensusApiRoute( } @Path("/allSlotsInfo") - @ApiOperation(value = "Get all slots' info", notes = "Get all slots' information", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of all slots details or error") + )) def allSlotsInfo: Route = (path("allSlotsInfo") & get) { val h = state.height val ret = Json.arr(Json.obj("height" -> h)) ++ JsArray( @@ -84,10 +92,13 @@ case class SposConsensusApiRoute( } @Path("/slotInfo/{slotId}") - @ApiOperation(value = "Minting average balance with slot ID", notes = "Account of supernode's minting average balance", httpMethod = "GET") + @ApiOperation(value = "Minting average balance with slot ID", notes = "Get the supernode's minting average balance by specified `slotId`", httpMethod = "GET") @ApiImplicitParams(Array( new ApiImplicitParam(name = "slotId", value = "Slot Id", required = true, dataType = "integer", paramType = "path") )) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the minting average balance of a specified slot info or error") + )) def mintingAverageBalanceId: Route = (path("slotInfo" / IntNumber) & get) { slotId => state.slotAddress(slotId) match { case None if slotId >= 0 && slotId < fs.numOfSlots => @@ -111,7 +122,7 @@ case class SposConsensusApiRoute( } @Path("/mintTime/{blockId}") - @ApiOperation(value = "Mint time", notes = "Mint time of a block with specified id", httpMethod = "GET") + @ApiOperation(value = "Mint time", notes = "Mint time of a block with specified `blockId`", httpMethod = "GET", response = classOf[Long]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "blockId", value = "Block id ", required = true, dataType = "string", paramType = "path") )) @@ -122,13 +133,16 @@ case class SposConsensusApiRoute( } @Path("/mintTime") - @ApiOperation(value = "Mint time last", notes = "Mint time of a last block", httpMethod = "GET") + @ApiOperation(value = "Mint time last", notes = "Mint time of a last block", httpMethod = "GET", response = classOf[Long]) def mintTime: Route = (path("mintTime") & get) { complete(Json.obj("mintTime" -> history.lastBlock.get.consensusData.mintTime)) } @Path("/algo") - @ApiOperation(value = "Consensus algo", notes = "Shows which consensus algo being using", httpMethod = "GET") + @ApiOperation(value = "Consensus algo", notes = "Shows which **consensus algo** are being used", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json with error or response like {\"consensusAlgo\": \"current adopting algo\"}") + )) def algo: Route = (path("algo") & get) { complete(Json.obj("consensusAlgo" -> "supernode-proof-of-stake (SPoS)")) } From db87ffca9d77953a6fc7add745dbed2d01d67b85 Mon Sep 17 00:00:00 2001 From: Julianxa Date: Mon, 1 Feb 2021 14:15:20 +0800 Subject: [PATCH 221/391] Improvement of payment API descriptions and examples --- .../vsys/api/http/payment/PaymentApiRoute.scala | 12 +++++------- .../scala/vsys/api/http/payment/PaymentRequest.scala | 4 ++-- .../vsys/api/http/payment/SignedPaymentRequest.scala | 6 +++--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/scala/vsys/api/http/payment/PaymentApiRoute.scala b/src/main/scala/vsys/api/http/payment/PaymentApiRoute.scala index f443ba051..28d553ee1 100755 --- a/src/main/scala/vsys/api/http/payment/PaymentApiRoute.scala +++ b/src/main/scala/vsys/api/http/payment/PaymentApiRoute.scala @@ -23,7 +23,7 @@ case class PaymentApiRoute(settings: RestAPISettings, wallet: Wallet, utx: UtxPo @Path("/payment") @ApiOperation(value = "Send payment from wallet.", - notes = "Send payment from wallet to another wallet. Each call sends new payment.", + notes = "Send payment from wallet to another wallet.", httpMethod = "POST", produces = "application/json", consumes = "application/json", @@ -34,12 +34,11 @@ case class PaymentApiRoute(settings: RestAPISettings, wallet: Wallet, utx: UtxPo value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.payment.PaymentRequest", - defaultValue = "{\n\t\"amount\":400,\n\t\"fee\":1,\n\t\"feeScale\":100,\n\t\"sender\":\"senderId\",\n\t\"recipient\":\"recipientId\",\n\t\"attachment\":\"5VECG3ZHwy\"\n}" + dataType = "vsys.api.http.payment.PaymentRequest" ) )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with response or error") + new ApiResponse(code = 200, message = "Successful Operation") )) def payment: Route = (path("payment") & post & withAuth) { json[PaymentRequest] { p => @@ -57,11 +56,10 @@ case class PaymentApiRoute(settings: RestAPISettings, wallet: Wallet, utx: UtxPo value = "Json with data", required = true, paramType = "body", - dataType = "vsys.api.http.payment.SignedPaymentRequest", - defaultValue = "{\n\t\"timestamp\": 0,\n\t\"amount\":400,\n\t\"fee\":1,\n\t\"feeScale\":100,\n\t\"senderPublicKey\":\"senderPubKey\",\n\t\"recipient\":\"recipientId\",\n\t\"attachment\":\"5VECG3ZHwy\",\n\t\"signature\":\"sig\"\n}" + dataType = "vsys.api.http.payment.SignedPaymentRequest" ) )) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) + @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def broadcastPayment: Route = (path("broadcast" / "payment") & post) { json[SignedPaymentRequest] { payment => doBroadcast(payment.toTx) diff --git a/src/main/scala/vsys/api/http/payment/PaymentRequest.scala b/src/main/scala/vsys/api/http/payment/PaymentRequest.scala index 12dfb9e1c..8b2e80a83 100644 --- a/src/main/scala/vsys/api/http/payment/PaymentRequest.scala +++ b/src/main/scala/vsys/api/http/payment/PaymentRequest.scala @@ -6,9 +6,9 @@ import play.api.libs.functional.syntax._ case class PaymentRequest( @ApiModelProperty(required = true) amount: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "10000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short, @ApiModelProperty(value = "Base58 encoded sender", required = true) sender: String, diff --git a/src/main/scala/vsys/api/http/payment/SignedPaymentRequest.scala b/src/main/scala/vsys/api/http/payment/SignedPaymentRequest.scala index 0010dea98..409f1f9f6 100644 --- a/src/main/scala/vsys/api/http/payment/SignedPaymentRequest.scala +++ b/src/main/scala/vsys/api/http/payment/SignedPaymentRequest.scala @@ -8,14 +8,14 @@ import vsys.api.http.BroadcastRequest import vsys.blockchain.state.ByteStr import vsys.blockchain.transaction.{PaymentTransaction, ValidationError} -@ApiModel(value = "Signed Payment transaction") +@ApiModel(value = "SignedPaymentTransaction") case class SignedPaymentRequest( @ApiModelProperty(required = true) timestamp: Long, @ApiModelProperty(required = true) amount: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "10000000") fee: Long, - @ApiModelProperty(required = true) + @ApiModelProperty(required = true, example = "100") feeScale: Short, @ApiModelProperty(value = "Recipient address", required = true) recipient: String, From 91115219cfec8cba51a878ed84bba622cf2b1740 Mon Sep 17 00:00:00 2001 From: Julianxa Date: Mon, 1 Feb 2021 14:17:02 +0800 Subject: [PATCH 222/391] Improvement of debug, node, peers, utils, wallet, transactions API descriptions and examples --- .../scala/vsys/api/http/NodeApiRoute.scala | 12 ++++++-- .../scala/vsys/api/http/PeersApiRoute.scala | 26 +++++++++-------- .../vsys/api/http/TransactionsApiRoute.scala | 29 ++++++++++++++----- .../scala/vsys/api/http/UtilsApiRoute.scala | 24 ++++++++------- .../scala/vsys/api/http/WalletApiRoute.scala | 3 ++ .../vsys/api/http/debug/DebugApiRoute.scala | 29 +++++++++++++------ 6 files changed, 81 insertions(+), 42 deletions(-) diff --git a/src/main/scala/vsys/api/http/NodeApiRoute.scala b/src/main/scala/vsys/api/http/NodeApiRoute.scala index 97ed5f1a9..339a4d822 100644 --- a/src/main/scala/vsys/api/http/NodeApiRoute.scala +++ b/src/main/scala/vsys/api/http/NodeApiRoute.scala @@ -24,9 +24,9 @@ case class NodeApiRoute(settings: RestAPISettings, } @Path("/version") - @ApiOperation(value = "Version", notes = "Get VSYS node version", httpMethod = "GET") + @ApiOperation(value = "Version", notes = "Get VSYS node version", httpMethod = "GET", response = classOf[String]) @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json VSYS node version") + new ApiResponse(code = 200, message = "Json response of VSYS node version") )) def version: Route = (get & path("version")) { complete(Json.obj("version" -> Constants.AgentName)) @@ -35,6 +35,9 @@ case class NodeApiRoute(settings: RestAPISettings, @Path("/stop") @ApiOperation(value = "Stop", notes = "Stop the node", httpMethod = "POST", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) def stop: Route = (post & path("stop") & withAuth) { log.info("Request to stop application") application.shutdown() @@ -42,7 +45,10 @@ case class NodeApiRoute(settings: RestAPISettings, } @Path("/status") - @ApiOperation(value = "Status", notes = "Get status of the running core", httpMethod = "GET") + @ApiOperation(value = "Status", notes = "Get **status** of the running core", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the node status or error") + )) def status: Route = (get & path("status")) { val lastUpdated = history.lastBlock.get.timestamp complete( diff --git a/src/main/scala/vsys/api/http/PeersApiRoute.scala b/src/main/scala/vsys/api/http/PeersApiRoute.scala index e9bb9453c..e96fe2e50 100755 --- a/src/main/scala/vsys/api/http/PeersApiRoute.scala +++ b/src/main/scala/vsys/api/http/PeersApiRoute.scala @@ -29,9 +29,9 @@ case class PeersApiRoute( } @Path("/all") - @ApiOperation(value = "Peer list", notes = "Peer list", httpMethod = "GET") + @ApiOperation(value = "Peer list", notes = "Get the peer list", httpMethod = "GET") @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with peer list or error") + new ApiResponse(code = 200, message = "Json response of a peer list or error") )) def allPeers: Route = (path("all") & get) { complete(Json.obj("peers" -> @@ -44,9 +44,9 @@ case class PeersApiRoute( } @Path("/connected") - @ApiOperation(value = "Connected peers list", notes = "Connected peers list", httpMethod = "GET") + @ApiOperation(value = "Connected peers list", notes = "Get the connected peers list", httpMethod = "GET") @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with connected peers or error") + new ApiResponse(code = 200, message = "Json response of a connected peers list or error") )) def connectedPeers: Route = (path("connected") & get) { val peers = establishedConnections.values().stream().map[JsValue](pi => Json.obj( @@ -64,14 +64,16 @@ case class PeersApiRoute( @Path("/connect") @ApiOperation(value = "Connect to peer", notes = "Connect to peer", httpMethod = "POST", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) @ApiImplicitParams(Array( new ApiImplicitParam( name = "body", - value = "Json with data", + value = "Peer host settings", required = true, paramType = "body", - dataType = "string", - defaultValue = "{\n\t\"host\":\"127.0.0.1\",\n\t\"port\":\"9084\"\n}" + dataType = "vsys.network.PeerNetworkConnection", ) )) def connect: Route = (path("connect") & post & withAuth) { @@ -84,10 +86,10 @@ case class PeersApiRoute( } @Path("/blacklisted") - @ApiOperation(value = "Blacklisted peers list", notes = "Blacklisted peers list", httpMethod = "GET") + @ApiOperation(value = "Blacklisted peers list", notes = "Get the blacklisted peers list", httpMethod = "GET") @ApiResponses( Array( - new ApiResponse(code = 200, message = "Json with blacklisted peers or error") + new ApiResponse(code = 200, message = "Json response of the blacklisted peers or error") )) def blacklistedPeers: Route = (path("blacklisted") & get) { complete( @@ -99,10 +101,10 @@ case class PeersApiRoute( } @Path("/suspended") - @ApiOperation(value = "Suspended peers list", notes = "Suspended peers list", httpMethod = "GET") + @ApiOperation(value = "Suspended peers list", notes = "Get the suspended peers list", httpMethod = "GET") @ApiResponses( Array( - new ApiResponse(code = 200, message = "JSON with suspended peers or error") + new ApiResponse(code = 200, message = "JSON response of a suspended peer list or error") )) def suspendedPeers: Route = (path("suspended") & get) { complete( @@ -115,7 +117,7 @@ case class PeersApiRoute( authorizations = Array(new Authorization("api_key"))) @ApiResponses( Array( - new ApiResponse(code = 200, message = "200") + new ApiResponse(code = 200, message = "Successful Operation") )) def clearBlacklist: Route = (path("clearblacklist") & post & withAuth) { peerDatabase.clearBlacklist() diff --git a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala index 45fc2f516..fb3d86272 100644 --- a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala +++ b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala @@ -12,7 +12,7 @@ import vsys.blockchain.state.ByteStr import vsys.blockchain.state.reader.StateReader import vsys.blockchain.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} import vsys.blockchain.transaction.TransactionParser.TransactionType -import vsys.blockchain.transaction.{Transaction, ProcessedTransaction} +import vsys.blockchain.transaction.{ProcessedTransaction, Transaction} import vsys.blockchain.UtxPool import vsys.settings.{RestAPISettings, StateSettings} @@ -130,7 +130,10 @@ case class TransactionsApiRoute( } @Path("/address/{address}/limit/{limit}") - @ApiOperation(value = "Address", notes = "Get list of transactions where specified address has been involved", httpMethod = "GET") + @ApiOperation(value = "Address", notes = "Get a transactions list with the `limit` size a specified `address` getting involved", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of a transcations list or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Wallet address ", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "limit", value = "Specified number of records to be returned", required = true, dataType = "integer", paramType = "path") @@ -163,8 +166,11 @@ case class TransactionsApiRoute( } @Path("/activeLeaseList/{address}") - @ApiOperation(value = "Address", notes = "Get list of active lease transactions", httpMethod = "GET", + @ApiOperation(value = "Address", notes = "Get a list of **active lease transactions** by a specified `address`", httpMethod = "GET", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response with a list of active lease transactions or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Wallet address ", required = true, dataType = "string", paramType = "path"), )) @@ -187,7 +193,10 @@ case class TransactionsApiRoute( } @Path("/info/{id}") - @ApiOperation(value = "Info", notes = "Get transaction info", httpMethod = "GET") + @ApiOperation(value = "Info", notes = "Get transaction info by a specified transaction `id`", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of transaction info or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "id", value = "transaction id ", required = true, dataType = "string", paramType = "path") )) @@ -210,7 +219,10 @@ case class TransactionsApiRoute( } @Path("/unconfirmed") - @ApiOperation(value = "Unconfirmed", notes = "Get list of unconfirmed transactions", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the unconfirmed transactions list or error") + )) + @ApiOperation(value = "Unconfirmed", notes = "Get a list of unconfirmed transactions", httpMethod = "GET") def unconfirmed: Route = (pathPrefix("unconfirmed") & get) { pathEndOrSingleSlash { complete(JsArray(utxPool.all().map(txToExtendedJson))) @@ -218,13 +230,16 @@ case class TransactionsApiRoute( } @Path("/unconfirmed/size") - @ApiOperation(value = "Size of UTX pool", notes = "Get number of unconfirmed transactions in the UTX pool", httpMethod = "GET") + @ApiOperation(value = "Size of UTX pool", notes = "Get the number of transactions in the unconfirmed transactions(UTX) pool", httpMethod = "GET", response = classOf[Int]) def utxSize: Route = (pathPrefix("size") & get) { complete(Json.obj("size" -> JsNumber(utxPool.size))) } @Path("/unconfirmed/info/{id}") - @ApiOperation(value = "Transaction Info", notes = "Get transaction that is in the UTX", httpMethod = "GET") + @ApiOperation(value = "Transaction Info", notes = "Get the **unconfirmed transaction** by a specified transaction `id`", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the unconfirmed transaction info or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "id", value = "Transaction id ", required = true, dataType = "string", paramType = "path") )) diff --git a/src/main/scala/vsys/api/http/UtilsApiRoute.scala b/src/main/scala/vsys/api/http/UtilsApiRoute.scala index 2bce9bc4e..247037d92 100755 --- a/src/main/scala/vsys/api/http/UtilsApiRoute.scala +++ b/src/main/scala/vsys/api/http/UtilsApiRoute.scala @@ -28,10 +28,10 @@ case class UtilsApiRoute(timeService: Time, settings: RestAPISettings) extends A } @Path("/time") - @ApiOperation(value = "Time", notes = "Current Node time (UTC)", httpMethod = "GET") + @ApiOperation(value = "Time", notes = "Get the Current Node time (UTC)", httpMethod = "GET") @ApiResponses( Array( - new ApiResponse(code = 200, message = "Json with time or error") + new ApiResponse(code = 200, message = "Json response of the current node time or error") )) def time: Route = (path("time") & get) { val t = System.currentTimeMillis()*1000000L + System.nanoTime()%1000000L @@ -41,30 +41,32 @@ case class UtilsApiRoute(timeService: Time, settings: RestAPISettings) extends A @Path("/seed") @ApiOperation(value = "Seed", notes = "Generate random seed", httpMethod = "GET") @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with peer list or error") + new ApiResponse(code = 200, message = "Json response of a random seed or error") )) def seedRoute: Route = (path("seed") & get) { complete(seed(DefaultSeedSize)) } @Path("/seed/{length}") - @ApiOperation(value = "Seed of specified length", notes = "Generate random seed of specified length", httpMethod = "GET") + @ApiOperation(value = "Seed of specified length", notes = "Generate random seed of specified `length`", httpMethod = "GET") @ApiImplicitParams(Array( new ApiImplicitParam(name = "length", value = "Seed length ", required = true, dataType = "integer", paramType = "path") )) - @ApiResponse(code = 200, message = "Json with error message") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of a random seed or error") + )) def length: Route = (path("seed" / IntNumber) & get) { length => if (length <= MaxSeedSize) complete(seed(length)) else complete(TooBigArrayAllocation) } @Path("/hash/secure") - @ApiOperation(value = "Hash", notes = "Return SecureCryptographicHash of specified message", httpMethod = "POST") + @ApiOperation(value = "Hash", notes = "Return a hash(SecureCryptographicHash) of a specified `message`", httpMethod = "POST") @ApiImplicitParams(Array( new ApiImplicitParam(name = "message", value = "Message to hash", required = true, paramType = "body", dataType = "string") )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with error or json like {\"message\": \"your message\",\"hash\": \"your message hash\"}") + new ApiResponse(code = 200, message = "Successful Operation") )) def hashSecure: Route = (path("hash" / "secure") & post) { entity(as[String]) { message => @@ -73,12 +75,12 @@ case class UtilsApiRoute(timeService: Time, settings: RestAPISettings) extends A } @Path("/hash/fast") - @ApiOperation(value = "Hash", notes = "Return FastCryptographicHash of specified message", httpMethod = "POST") + @ApiOperation(value = "Hash", notes = "Return a hash(FastCryptographicHash) of a specified `message`", httpMethod = "POST") @ApiImplicitParams(Array( new ApiImplicitParam(name = "message", value = "Message to hash", required = true, paramType = "body", dataType = "string") )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with error or json like {\"message\": \"your message\",\"hash\": \"your message hash\"}") + new ApiResponse(code = 200, message = "Successful Operation") )) def hashFast: Route = (path("hash" / "fast") & post) { entity(as[String]) { message => @@ -88,13 +90,13 @@ case class UtilsApiRoute(timeService: Time, settings: RestAPISettings) extends A @Path("/sign/{privateKey}") - @ApiOperation(value = "Hash", notes = "Return FastCryptographicHash of specified message", httpMethod = "POST") + @ApiOperation(value = "Hash", notes = "Return a hash(FastCryptographicHash) of a specified message with the `privateKey`", httpMethod = "POST") @ApiImplicitParams(Array( new ApiImplicitParam(name = "privateKey", value = "privateKey", required = true, paramType = "path", dataType = "string"), new ApiImplicitParam(name = "message", value = "Message to hash", required = true, paramType = "body", dataType = "string") )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with error or json like {\"message\": \"your message\",\"hash\": \"your message hash\"}") + new ApiResponse(code = 200, message = "Successful Operation") )) def sign: Route = (path("sign" / Segment) & post) {pk => entity(as[String]) { message => diff --git a/src/main/scala/vsys/api/http/WalletApiRoute.scala b/src/main/scala/vsys/api/http/WalletApiRoute.scala index a48ae2929..090ef7245 100644 --- a/src/main/scala/vsys/api/http/WalletApiRoute.scala +++ b/src/main/scala/vsys/api/http/WalletApiRoute.scala @@ -17,6 +17,9 @@ case class WalletApiRoute(settings: RestAPISettings, wallet: Wallet) extends Api @Path("/seed") @ApiOperation(value = "Seed", notes = "Export wallet seed", httpMethod = "GET", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of a wallet seed or error") + )) def seed: Route = (path("wallet" / "seed") & get & withAuth) { complete(Json.obj("seed" -> wallet.seed)) } diff --git a/src/main/scala/vsys/api/http/debug/DebugApiRoute.scala b/src/main/scala/vsys/api/http/debug/DebugApiRoute.scala index 7dc1b3c21..08087de32 100644 --- a/src/main/scala/vsys/api/http/debug/DebugApiRoute.scala +++ b/src/main/scala/vsys/api/http/debug/DebugApiRoute.scala @@ -48,6 +48,9 @@ case class DebugApiRoute(settings: RestAPISettings, } @Path("/blocks/{howMany}") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the sizes and full hashes for last blocks or error") + )) @ApiOperation(value = "Blocks", notes = "Get sizes and full hashes for last blocks", httpMethod = "GET", authorizations = Array(new Authorization("api_key"))) @ApiImplicitParams(Array( @@ -70,7 +73,9 @@ case class DebugApiRoute(settings: RestAPISettings, @Path("/state") @ApiOperation(value = "State", notes = "Get current state", httpMethod = "GET", authorizations = Array(new Authorization("api_key"))) - @ApiResponses(Array(new ApiResponse(code = 200, message = "Json state"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the current state or error") + )) def state: Route = (path("state") & get & withAuth) { complete(stateReader.accountPortfolios .map { case (k, v) => @@ -82,7 +87,7 @@ case class DebugApiRoute(settings: RestAPISettings, @Path("/portfolios/{address}") @ApiOperation( value = "Portfolio", - notes = "Get current portfolio considering pessimistic transactions in the UTX pool", + notes = "Get current portfolio considering pessimistic transactions in the unconfirmed transactions(UTX) pool by a speicified `address`", httpMethod = "GET", authorizations = Array(new Authorization("api_key")) ) @@ -116,8 +121,11 @@ case class DebugApiRoute(settings: RestAPISettings, } @Path("/stateVsys/{height}") - @ApiOperation(value = "State at block", notes = "Get state at specified height", httpMethod = "GET", + @ApiOperation(value = "State at block", notes = "Get the **state** at a specified `height`", httpMethod = "GET", authorizations = Array(new Authorization("api_key"))) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the address/balance pairing or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "height", value = "height", required = true, dataType = "integer", paramType = "path") )) @@ -155,7 +163,7 @@ case class DebugApiRoute(settings: RestAPISettings, ) )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "200 if success, 404 if there are no block at this height") + new ApiResponse(code = 200, message = "Successful Operation") )) def rollback: Route = withAuth { (path("rollback") & post) { @@ -171,9 +179,9 @@ case class DebugApiRoute(settings: RestAPISettings, } @Path("/info") - @ApiOperation(value = "State", notes = "All info you need to debug", httpMethod = "GET") + @ApiOperation(value = "State", notes = "Get all info you need to debug", httpMethod = "GET") @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json state") + new ApiResponse(code = 200, message = "Json response of the debug info or error") )) def info: Route = (path("info") & get & withAuth) { complete(Json.obj( @@ -184,7 +192,10 @@ case class DebugApiRoute(settings: RestAPISettings, @Path("/rollback-to/{signature}") - @ApiOperation(value = "Block signature", notes = "Rollback the state to the block with a given signature", httpMethod = "DELETE", + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Successful Operation") + )) + @ApiOperation(value = "Block signature", notes = "Rollback the state to the block with a given `signature`", httpMethod = "DELETE", authorizations = Array(new Authorization("api_key"))) @ApiImplicitParams(Array( new ApiImplicitParam(name = "signature", value = "Base58-encoded block signature", required = true, dataType = "string", paramType = "path") @@ -201,13 +212,13 @@ case class DebugApiRoute(settings: RestAPISettings, } @Path("/blacklist") - @ApiOperation(value = "Blacklist given peer", notes = "Moving peer to blacklist", httpMethod = "POST", + @ApiOperation(value = "Blacklist given peer", notes = "Moving peer to blacklist by a specified node `address`", httpMethod = "POST", authorizations = Array(new Authorization("api_key"))) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "IP address of node", required = true, dataType = "string", paramType = "body") )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "200 if success, 404 if there are no peer with such address") + new ApiResponse(code = 200, message = "Successful Operation") )) def blacklist: Route = withAuth { (path("blacklist") & post) { From 69f6d4c83a69edb3b54745dac78d6ad475d05cf7 Mon Sep 17 00:00:00 2001 From: Julianxa Date: Mon, 1 Feb 2021 14:17:27 +0800 Subject: [PATCH 223/391] Improvement of block API descriptions and examples --- .../scala/vsys/api/http/BlocksApiRoute.scala | 47 +++++++++++++------ .../scala/vsys/blockchain/block/Block.scala | 6 ++- .../vsys/blockchain/block/BlockField.scala | 2 + 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/main/scala/vsys/api/http/BlocksApiRoute.scala b/src/main/scala/vsys/api/http/BlocksApiRoute.scala index e5810fcce..f4ebec941 100644 --- a/src/main/scala/vsys/api/http/BlocksApiRoute.scala +++ b/src/main/scala/vsys/api/http/BlocksApiRoute.scala @@ -1,7 +1,6 @@ package vsys.api.http import javax.ws.rs.Path - import akka.http.scaladsl.marshalling.ToResponseMarshallable import akka.http.scaladsl.server.Route import io.netty.channel.group.ChannelGroup @@ -13,7 +12,6 @@ import vsys.blockchain.state.ByteStr import vsys.blockchain.transaction.TransactionParser import vsys.network._ import vsys.settings.{CheckpointsSettings, RestAPISettings} - import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -31,7 +29,10 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp } @Path("/address/{address}/{from}/{to}") - @ApiOperation(value = "Address", notes = "Get list of blocks generated by specified address", httpMethod = "GET") + @ApiOperation(value = "Address", notes = "Get a block list generated by a specified `address` and a block height range (`from`/`to`)", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the block list or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "from", value = "Start block height", required = true, dataType = "integer", paramType = "path"), new ApiImplicitParam(name = "to", value = "End block height", required = true, dataType = "integer", paramType = "path"), @@ -52,10 +53,13 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp } @Path("/child/{signature}") - @ApiOperation(value = "Child", notes = "Get children of specified block", httpMethod = "GET") + @ApiOperation(value = "Child", notes = "Get children of a specified block by the base58-encoded `signature`", httpMethod = "GET") @ApiImplicitParams(Array( new ApiImplicitParam(name = "signature", value = "Base58-encoded signature", required = true, dataType = "string", paramType = "path") )) + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the child block information or error") + )) def child: Route = (path("child" / Segment) & get) { encodedSignature => withBlock(history, encodedSignature) { block => complete(history.child(block).map(_.json + ("transaction count" -> Json.toJson(block.transactionData.length))).getOrElse[JsObject]( @@ -65,7 +69,7 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp @Path("/delay/{signature}/{blockNum}") @ApiOperation(value = "Average delay", - notes = "Average delay in milliseconds between last `blockNum` blocks starting from block with `signature`", httpMethod = "GET") + notes = "Get the average delay in milliseconds between last `blockNum` blocks starting from block with `signature`", httpMethod = "GET", response = classOf[Long]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "signature", value = "Base58-encoded signature", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "blockNum", value = "Number of blocks to count delay", required = true, dataType = "string", paramType = "path") @@ -78,7 +82,7 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp } @Path("/height/{signature}") - @ApiOperation(value = "Height", notes = "Get height of a block by its Base58-encoded signature", httpMethod = "GET") + @ApiOperation(value = "Height", notes = "Get the **block height** by its Base58-encoded `signature`", httpMethod = "GET", response = classOf[Int]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "signature", value = "Base58-encoded signature", required = true, dataType = "string", paramType = "path") )) @@ -95,13 +99,16 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp } @Path("/height") - @ApiOperation(value = "Height", notes = "Get blockchain height", httpMethod = "GET") + @ApiOperation(value = "Height", notes = "Get blockchain height", httpMethod = "GET", response=classOf[Int]) def height: Route = (path("height") & get) { complete(Json.obj("height" -> history.height())) } @Path("/at/{height}") - @ApiOperation(value = "At", notes = "Get block at specified height", httpMethod = "GET") + @ApiOperation(value = "At", notes = "Get block at specified `height`", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of a block details at a specified height or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "height", value = "Block height", required = true, dataType = "integer", paramType = "path") )) @@ -113,7 +120,10 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp } @Path("/seq/{from}/{to}") - @ApiOperation(value = "Seq", notes = "Get block at specified heights", httpMethod = "GET") + @ApiOperation(value = "Seq", notes = "Get block at the specified height range (`from`/`to`)", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the block list or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "from", value = "Start block height", required = true, dataType = "integer", paramType = "path"), new ApiImplicitParam(name = "to", value = "End block height", required = true, dataType = "integer", paramType = "path") @@ -130,7 +140,10 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp @Path("/last") - @ApiOperation(value = "Last", notes = "Get last block data", httpMethod = "GET") + @ApiOperation(value = "Last", notes = "Get the **last block** data", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the last block information or error") + )) def last: Route = (path("last") & get) { val height = history.height() val lastBlock = history.blockAt(height).get @@ -138,13 +151,19 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp } @Path("/first") - @ApiOperation(value = "First", notes = "Get genesis block data", httpMethod = "GET") + @ApiOperation(value = "First", notes = "Get the **genesis block** data", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the first block details or error") + )) def first: Route = (path("first") & get) { complete(history.genesis.json + ("height" -> Json.toJson(1)) + ("transaction count" -> Json.toJson(history.genesis.transactionData.length))) } @Path("/signature/{signature}") - @ApiOperation(value = "Signature", notes = "Get block by a specified Base58-encoded signature", httpMethod = "GET") + @ApiOperation(value = "Signature", notes = "Get block by a specified Base58-encoded `signature`", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response of the block details or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "signature", value = "Base58-encoded signature", required = true, dataType = "string", paramType = "path") )) @@ -159,13 +178,13 @@ case class BlocksApiRoute(settings: RestAPISettings, checkpointsSettings: Checkp } @Path("/checkpoint") - @ApiOperation(value = "Checkpoint", notes = "Broadcast checkpoint of blocks", httpMethod = "POST") + @ApiOperation(value = "Checkpoint", notes = "Broadcast the checkpoint of blocks", httpMethod = "POST") @ApiImplicitParams(Array( new ApiImplicitParam(name = "message", value = "Checkpoint message", required = true, paramType = "body", dataType = "vsys.network.Checkpoint") )) @ApiResponses(Array( - new ApiResponse(code = 200, message = "Json with response or error") + new ApiResponse(code = 200, message = "Successful Operation") )) def checkpoint: Route = (path("checkpoint") & post) { json[Checkpoint] { checkpoint => diff --git a/src/main/scala/vsys/blockchain/block/Block.scala b/src/main/scala/vsys/blockchain/block/Block.scala index 656d20cf7..b14753861 100755 --- a/src/main/scala/vsys/blockchain/block/Block.scala +++ b/src/main/scala/vsys/blockchain/block/Block.scala @@ -10,7 +10,7 @@ import vsys.blockchain.transaction._ import vsys.settings.GenesisSettings import vsys.utils.crypto.EllipticCurveImpl import vsys.utils.ScorexLogging - +import io.swagger.annotations._ import scala.util.{Failure, Try} case class Block(timestamp: Long, version: Byte, reference: ByteStr, signerData: SignerData, @@ -31,6 +31,7 @@ case class Block(timestamp: Long, version: Byte, reference: ByteStr, signerData: lazy val fee: Long = transactionData.map(_.transaction.transactionFee).sum + @ApiModelProperty(hidden= true) lazy val json: JsObject = versionField.json ++ timestampField.json ++ @@ -45,6 +46,7 @@ case class Block(timestamp: Long, version: Byte, reference: ByteStr, signerData: "blocksize" -> bytes.length ) + @ApiModelProperty(hidden= true) lazy val bytes: Array[Byte] = { val txBytesSize = transactionDataField.bytes.length val txBytes = Bytes.ensureCapacity(Ints.toByteArray(txBytesSize), 4, 0) ++ transactionDataField.bytes @@ -69,9 +71,11 @@ case class Block(timestamp: Long, version: Byte, reference: ByteStr, signerData: // set blockScore to minting Balance / 100000000 val sc = Math.max(consensusData.mintBalance / 100000000L, 1L) + @ApiModelProperty(hidden= true) lazy val blockScore: BigInt = BigInt(sc.toString) // destroy transaction fee + @ApiModelProperty(hidden= true) lazy val feesDistribution: Diff = Diff.empty override lazy val signatureValid: Boolean = EllipticCurveImpl.verify(signerData.signature.arr, bytesWithoutSignature, signerData.generator.publicKey) diff --git a/src/main/scala/vsys/blockchain/block/BlockField.scala b/src/main/scala/vsys/blockchain/block/BlockField.scala index 3310f39f4..37714171f 100755 --- a/src/main/scala/vsys/blockchain/block/BlockField.scala +++ b/src/main/scala/vsys/blockchain/block/BlockField.scala @@ -8,6 +8,7 @@ import vsys.account.PublicKeyAccount import vsys.blockchain.state.ByteStr import vsys.blockchain.transaction.{Transaction, ProcessedTransaction} import vsys.utils.serialization.{BytesSerializable, JsonSerializable} +import io.swagger.annotations._ /** * An abstraction of a part of a block, wrapping some data. The wrapper interface @@ -47,6 +48,7 @@ case class TransactionBlockField(override val name: String, override val value: override lazy val bytes: Array[Byte] = value.bytes } +@ApiModelProperty(hidden= true) case class SignerData(generator: PublicKeyAccount, signature: ByteStr) case class SignerDataBlockField(override val name: String, override val value: SignerData) From 0edec760f968a1a8786594450f843b5af8d172ca Mon Sep 17 00:00:00 2001 From: Julianxa Date: Mon, 1 Feb 2021 14:18:21 +0800 Subject: [PATCH 224/391] Improvement of network API descriptions and examples --- src/main/scala/vsys/network/PeerDatabaseImpl.scala | 2 +- src/main/scala/vsys/network/PeerInfo.scala | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/network/PeerDatabaseImpl.scala b/src/main/scala/vsys/network/PeerDatabaseImpl.scala index c29191a91..e8ef19902 100755 --- a/src/main/scala/vsys/network/PeerDatabaseImpl.scala +++ b/src/main/scala/vsys/network/PeerDatabaseImpl.scala @@ -75,7 +75,7 @@ class PeerDatabaseImpl(settings: NetworkSettings) extends PeerDatabase with Auto removeObsoleteRecords(suspension, settings.suspensionResidenceTime.toMillis).keySet().asScala.toSet override def detailedBlacklist: Map[InetAddress, (Long, String)] = - removeObsoleteRecords(suspension, settings.blackListResidenceTime.toMillis).asScala.map{ + removeObsoleteRecords(blacklist, settings.blackListResidenceTime.toMillis).asScala.map{ case ((h, t)) => h -> ((t, Option(reasons.get(h)).getOrElse(""))) }.toMap diff --git a/src/main/scala/vsys/network/PeerInfo.scala b/src/main/scala/vsys/network/PeerInfo.scala index c2d85221f..ebb970f2c 100644 --- a/src/main/scala/vsys/network/PeerInfo.scala +++ b/src/main/scala/vsys/network/PeerInfo.scala @@ -1,6 +1,12 @@ package vsys.network import java.net.InetSocketAddress +import io.swagger.annotations._ + +case class PeerNetworkConnection(@ApiModelProperty(required = true, example = "127.0.0.1") + address: String, + @ApiModelProperty(required = true, example = "0") + port: Int) case class PeerInfo( remoteAddress: InetSocketAddress, From 13245263acf28f906cae662a973697beaffe3660 Mon Sep 17 00:00:00 2001 From: Julianxa Date: Mon, 1 Feb 2021 14:18:55 +0800 Subject: [PATCH 225/391] Improvement of transaction API descriptions and remove unnecessary models from API --- .../vsys/api/http/swagger/SwaggerDocService.scala | 5 +++++ .../blockchain/transaction/MintingTransaction.scala | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/api/http/swagger/SwaggerDocService.scala b/src/main/scala/vsys/api/http/swagger/SwaggerDocService.scala index aeb35d441..8311c0d86 100755 --- a/src/main/scala/vsys/api/http/swagger/SwaggerDocService.scala +++ b/src/main/scala/vsys/api/http/swagger/SwaggerDocService.scala @@ -59,6 +59,11 @@ class SwaggerDocService(val actorSystem: ActorSystem, val materializer: ActorMat val filteredPaths: Map[String, Path] = swagger.getPaths().asScala.toMap.filterKeys(cumstomPathsConfig.getOrElse(_, true)) swagger.addSecurityDefinition("api_key", new ApiKeyAuthDefinition("api_key", In.HEADER)) swagger.paths(collection.mutable.Map(filteredPaths.toSeq: _*).asJava) + val unwantedDefinitions: Seq[String] = Seq("Function1", "Function1RequestContextFutureRouteResult") + if (unwantedDefinitions.nonEmpty) { + swagger.setDefinitions(swagger.getDefinitions.asScala.filterKeys(definitionName => !unwantedDefinitions.contains(definitionName)).asJava) + } + swagger } //Let swagger-ui determine the host and port diff --git a/src/main/scala/vsys/blockchain/transaction/MintingTransaction.scala b/src/main/scala/vsys/blockchain/transaction/MintingTransaction.scala index c0acc6a6e..95c0bc62a 100644 --- a/src/main/scala/vsys/blockchain/transaction/MintingTransaction.scala +++ b/src/main/scala/vsys/blockchain/transaction/MintingTransaction.scala @@ -9,12 +9,16 @@ import vsys.account.Address import vsys.utils.crypto.hash.FastCryptographicHash import vsys.blockchain.transaction.TransactionParser._ import vsys.blockchain.consensus.SPoSCalc._ - +import io.swagger.annotations._ import scala.util.{Failure, Success, Try} -case class MintingTransaction private(recipient: Address, +case class MintingTransaction private(@ApiModelProperty(required = true) + recipient: Address, + @ApiModelProperty(required = true) amount: Long, + @ApiModelProperty(required = true) timestamp: Long, + @ApiModelProperty(required = true) currentBlockHeight: Int) extends NonFeeTransaction { val transactionType = TransactionType.MintingTransaction @@ -39,7 +43,7 @@ case class MintingTransaction private(recipient: Address, ) override lazy val bytes: Array[Byte] = Bytes.concat(toSign) - + } object MintingTransaction extends TransactionParser { From d4104cdf1ff60c89c9160d6a6df407f1c4b614cd Mon Sep 17 00:00:00 2001 From: twwu123 Date: Mon, 1 Feb 2021 14:25:41 +0800 Subject: [PATCH 226/391] Allow V Stable Swap as valid contract --- src/main/scala/vsys/blockchain/contract/Contract.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index dd475eef0..86a0deb18 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -151,7 +151,8 @@ object Contract extends ScorexLogging { !(bytes sameElements ContractLock.contract.bytes.arr) && !(bytes sameElements ContractNonFungible.contract.bytes.arr) && !(bytes sameElements ContractPaymentChannel.contract.bytes.arr) && - !(bytes sameElements ContractVSwap.contract.bytes.arr)) { + !(bytes sameElements ContractVSwap.contract.bytes.arr) && + !(bytes sameElements ContractVStableSwap.contract.bytes.arr)) { log.warn(s"Illegal contract ${bytes.mkString(" ")}") false } else if (textualStr.isFailure || From 830dae4575a3df4f63fc2571c0fdcccf817005b0 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Mon, 1 Feb 2021 14:26:57 +0800 Subject: [PATCH 227/391] Check if base and target token is the same before deposit in V Stable Swap --- .../vsys/blockchain/contract/ContractVStableSwap.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 4ec07dc35..3c56f7925 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -90,7 +90,7 @@ object ContractVStableSwap { val depositId: Short = 1 val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId") ++ Seq("baseTokenId", "targetTokenId", "isValidTokenId", - "isBaseToken", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock") + "isBaseToken", "baseTokenIfBlock", "isTargetToken", "valueFalse", "targetTokenIfBlock") val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) val depositTriggerOpcs: Seq[Array[Byte]] = Seq( assertCaller ++ Array(0.toByte), @@ -105,14 +105,16 @@ object ContractVStableSwap { ) ), DataType.OpcBlock).bytes ++ Array(7.toByte), compareBytesEqual ++ Array(2.toByte, 4.toByte, 8.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(9.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(5.toByte, 9.toByte), cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(9.toByte), + ), DataType.OpcBlock).bytes ++ Array(10.toByte), conditionIf ++ Array(6.toByte, 7.toByte), - conditionIf ++ Array(8.toByte, 9.toByte), + conditionIf ++ Array(8.toByte, 10.toByte), assertTrue ++ Array(5.toByte) ) lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) From f957469817f31e5b4dead3f5eba693b8356827b5 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Mon, 1 Feb 2021 14:28:10 +0800 Subject: [PATCH 228/391] Add Test function generation for V Stable Swap --- .../vstableswap/VStableSwapContractGen.scala | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala diff --git a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala new file mode 100644 index 000000000..05117d5b9 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala @@ -0,0 +1,249 @@ +package vsys.blockchain.contract.vstableswap + +import com.google.common.primitives.Longs +import org.scalacheck.Gen +import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract._ +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.state._ +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +trait VStableSwapContractGen { + + val supersedeIndex: Short = 0 + val setOrderIndex: Short = 1 + val updateIndex: Short = 2 + val orderDepositIndex: Short = 3 + val orderWithdrawIndex: Short = 4 + val closeIndex: Short = 5 + val swapBaseToTargetIndex: Short = 6 + val swapTargetToBaseIndex: Short = 7 + + def vStableSwapContractGen(): Gen[Contract] = ContractVStableSwap.contract + + def genesisVStableSwapGen(rep: PrivateKeyAccount, + ts: Long): Gen[GenesisTransaction] = + GenesisTransaction.create(rep, ENOUGH_AMT, -1, ts).explicitGet() + + def registerVStableSwapGen(signer: PrivateKeyAccount, + contract: Contract, + dataStack: Seq[DataEntry], + description: String, + fee: Long, + ts: Long): Gen[RegisterContractTransaction] = + RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() + + def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + addr <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) + } yield Seq(addr) + + def setOrderDataStackGen(feeBase: Long, + feeTarget: Long, + minBase: Long, + maxBase: Long, + minTarget: Long, + maxTarget: Long, + priceBase: Long, + priceTarget: Long, + baseDeposit: Long, + targetDeposit: Long): Gen[Seq[DataEntry]] = for { + feeBase <- Gen.const(DataEntry(Longs.toByteArray(feeBase), DataType.Amount)) + feeTarget <- Gen.const(DataEntry(Longs.toByteArray(feeTarget), DataType.Amount)) + minBase <- Gen.const(DataEntry(Longs.toByteArray(minBase), DataType.Amount)) + maxBase <- Gen.const(DataEntry(Longs.toByteArray(maxBase), DataType.Amount)) + minTarget <- Gen.const(DataEntry(Longs.toByteArray(minTarget), DataType.Amount)) + maxTarget <- Gen.const(DataEntry(Longs.toByteArray(maxTarget), DataType.Amount)) + priceBase <- Gen.const(DataEntry(Longs.toByteArray(priceBase), DataType.Amount)) + priceTarget <- Gen.const(DataEntry(Longs.toByteArray(priceTarget), DataType.Amount)) + baseDeposit <- Gen.const(DataEntry(Longs.toByteArray(baseDeposit), DataType.Amount)) + targetDeposit <- Gen.const(DataEntry(Longs.toByteArray(targetDeposit), DataType.Amount)) + } yield Seq(feeBase, feeTarget, minBase, maxBase, minTarget, maxTarget, priceBase, priceTarget, baseDeposit, targetDeposit) + + def updateDataStackGen(orderId: Array[Byte], + feeBase: Long, + feeTarget: Long, + minBase: Long, + minTarget: Long, + maxTarget: Long): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + feeBase <- Gen.const(DataEntry(Longs.toByteArray(feeBase), DataType.Amount)) + feeTarget <- Gen.const(DataEntry(Longs.toByteArray(feeTarget), DataType.Amount)) + minBase <- Gen.const(DataEntry(Longs.toByteArray(minBase), DataType.Amount)) + minTarget <- Gen.const(DataEntry(Longs.toByteArray(minTarget), DataType.Amount)) + maxTarget <- Gen.const(DataEntry(Longs.toByteArray(maxTarget), DataType.Amount)) + } yield Seq(orderId, feeBase, feeTarget, minBase, minTarget, maxTarget) + + def orderDepositDataStackGen(orderId: Array[Byte], + baseDeposit: Long, + targetDeposit: Long): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + baseDeposit <- Gen.const(DataEntry(Longs.toByteArray(baseDeposit), DataType.Amount)) + targetDeposit <- Gen.const(DataEntry(Longs.toByteArray(targetDeposit), DataType.Amount)) + } yield Seq(orderId, baseDeposit, targetDeposit) + + def orderWithdrawDataStackGen(orderId: Array[Byte], + baseWithdraw: Long, + targetWithdraw: Long): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + baseWithdraw <- Gen.const(DataEntry(Longs.toByteArray(baseWithdraw), DataType.Amount)) + targetWithdraw <- Gen.const(DataEntry(Longs.toByteArray(targetWithdraw), DataType.Amount)) + } yield Seq(orderId, baseWithdraw, targetWithdraw) + + def closeDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + } yield Seq(orderId) + + def swapBaseToTargetDataStackGen(orderId: Array[Byte], + amount: Long, + fee: Long, + price: Long, + deadLine: Long): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + amount <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) + fee <- Gen.const(DataEntry(Longs.toByteArray(fee), DataType.Amount)) + price <- Gen.const(DataEntry(Longs.toByteArray(price), DataType.Amount)) + deadLine <- Gen.const(DataEntry(Longs.toByteArray(deadLine), DataType.Timestamp)) + } yield Seq(orderId, amount, fee, price, deadLine) + + def swapTargetToBaseDataStackGen(orderId: Array[Byte], + amount: Long, + fee: Long, + price: Long, + deadLine: Long): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + amount <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) + fee <- Gen.const(DataEntry(Longs.toByteArray(fee), DataType.Amount)) + price <- Gen.const(DataEntry(Longs.toByteArray(price), DataType.Amount)) + deadLine <- Gen.const(DataEntry(Longs.toByteArray(deadLine), DataType.Timestamp)) + } yield Seq(orderId, amount, fee, price, deadLine) + + def initVStableSwapDataStackGen(baseTokenId: Array[Byte], + targetTokenId: Array[Byte], + maxOrderPerUser: Long, + unitPriceBase: Long, + unitPriceTarget: Long): Gen[Seq[DataEntry]] = for { + baseTokenId <- Gen.const(DataEntry.create(baseTokenId, DataType.TokenId).right.get) + targetTokenId <- Gen.const(DataEntry.create(targetTokenId, DataType.TokenId).right.get) + maxOrderPerUser <- Gen.const(DataEntry.create(Longs.toByteArray(maxOrderPerUser), DataType.Amount).right.get) + unitPriceBase <- Gen.const(DataEntry.create(Longs.toByteArray(unitPriceBase), DataType.Amount).right.get) + unitPriceTarget <- Gen.const(DataEntry.create(Longs.toByteArray(unitPriceTarget), DataType.Amount).right.get) + } yield Seq(baseTokenId, targetTokenId, maxOrderPerUser, unitPriceBase, unitPriceTarget) + + def setOrderVStableSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + feeBase: Long, + feeTarget: Long, + minBase: Long, + maxBase: Long, + minTarget: Long, + maxTarget: Long, + priceBase: Long, + priceTarget: Long, + baseDeposit: Long, + targetDeposit: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = setOrderIndex + for { + data: Seq[DataEntry] <- setOrderDataStackGen(feeBase, feeTarget, minBase, maxBase, minTarget, maxTarget, priceBase, priceTarget, baseDeposit, targetDeposit) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def updateVStableSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + feeBase: Long, + feeTarget: Long, + minBase: Long, + minTarget: Long, + maxTarget: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = updateIndex + for { + data: Seq[DataEntry] <- updateDataStackGen(orderId, feeBase, feeTarget, minBase, minTarget, maxTarget) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def orderDepositVStableSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + baseDeposit: Long, + targetDeposit: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = orderDepositIndex + for { + data: Seq[DataEntry] <- orderDepositDataStackGen(orderId, baseDeposit, targetDeposit) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def orderWithdrawVStableSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + baseWithdraw: Long, + targetWithdraw: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = orderWithdrawIndex + for { + data: Seq[DataEntry] <- orderWithdrawDataStackGen(orderId, baseWithdraw, targetWithdraw) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def closeVStableSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = closeIndex + for { + data: Seq[DataEntry] <- closeDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def swapBaseToTargetVStableSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + amount: Long, + swapFee: Long, + price: Long, + deadLine: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = swapBaseToTargetIndex + for { + data: Seq[DataEntry] <- swapBaseToTargetDataStackGen(orderId, amount, swapFee, price, deadLine) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def swapTargetToBaseVStableSwapGen(sender: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + amount: Long, + swapFee: Long, + price: Long, + deadLine: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = swapTargetToBaseIndex + for { + data: Seq[DataEntry] <- swapTargetToBaseDataStackGen(orderId, amount, swapFee, price, deadLine) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } +} \ No newline at end of file From 7da8bb572f6bd4753e81d60c12e5840d7aeca6bb Mon Sep 17 00:00:00 2001 From: twwu123 Date: Mon, 1 Feb 2021 14:30:25 +0800 Subject: [PATCH 229/391] Add Helper functions for V Stable Swap Test --- .../VStableSwapFunctionHelperGen.scala | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunctionHelperGen.scala diff --git a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunctionHelperGen.scala new file mode 100644 index 000000000..ddbd20772 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunctionHelperGen.scala @@ -0,0 +1,107 @@ +package vsys.blockchain.contract.vstableswap + +import com.google.common.primitives.{Ints, Longs} +import org.scalacheck.Gen +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.{DataEntry, DataType} +import vsys.blockchain.contract.token.TokenContractGen +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +trait VStableSwapFunctionHelperGen extends VStableSwapContractGen with TokenContractGen { + + override val supersedeIndex: Short = 0 + + override def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + addr <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) + } yield Seq(addr) + + def registerToken(user: PrivateKeyAccount, + totalSupply: Long, + unity: Long, + desc: String, + fee: Long, + timestamp: Long): Gen[RegisterContractTransaction] = for { + initTokenDataStack: Seq[DataEntry] <- initTokenDataStackGen(totalSupply, unity, desc) + description <- validDescStringGen + tokenContract <- tokenContractGen(false) + regTokenContract <- registerTokenGen(user, tokenContract, initTokenDataStack, description, fee, timestamp) + } yield regTokenContract + + def issueToken(user: PrivateKeyAccount, + contractId: ContractAccount, + issueAmount: Long, + fee: Long, + timestamp: Long): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issueToken <- issueTokenGen(user, contractId, issueAmount, attach, fee, timestamp) + } yield issueToken + + def depositToken(user: PrivateKeyAccount, + contractId: ContractAccount, + sender: Array[Byte], + contract: Array[Byte], + amount: Long, + fee: Long, + timestamp: Long + ): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + depositTokenData = Seq(sender, contract, Longs.toByteArray(amount)) + depositTokenDataType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + depositToken <- depositTokenGen(user, contractId, false, depositTokenData, depositTokenDataType, attach, fee, timestamp) + } yield depositToken + + def withdrawToken(user: PrivateKeyAccount, + contractId: ContractAccount, + contract: Array[Byte], + sender: Array[Byte], + amount: Long, + fee: Long, + timestamp: Long): Gen[ExecuteContractFunctionTransaction] = for { + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + withdrawTokenData = Seq(contract, sender, Longs.toByteArray(amount)) + withdrawTokenDataType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + withdrawToken <- withdrawTokenGen(user, contractId, false, withdrawTokenData, withdrawTokenDataType, attach, fee, timestamp) + } yield withdrawToken + + def createBaseTokenTargetTokenAndInitVStableSwap(totalSupplyBase: Long, + unityBase: Long, + issueAmountBase: Long, + totalSupplyTarget: Long, + unityTarget: Long, + issueAmountTarget: Long, + maxOrderPerUser: Long, + unitPriceBase: Long, + unitPriceTarget: Long): Gen[(GenesisTransaction, GenesisTransaction, + PrivateKeyAccount, PrivateKeyAccount, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, Long, Long, Array[Byte])] = for { + (master, ts, fee) <- basicContractTestGen() + genesis <- genesisVStableSwapGen(master, ts) + user <- accountGen + genesis2 <- genesisVStableSwapGen(user, ts) + vStableSwapContract <- vStableSwapContractGen() + // Register base token + regTokenBase <- registerToken(master, totalSupplyBase, unityBase, "init", fee, ts) + tokenBaseContractId = regTokenBase.contractId + tokenBaseId = tokenIdFromBytes(tokenBaseContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // Register target token + regTokenTarget <- registerToken(master, totalSupplyTarget, unityTarget, "init", fee, ts + 1) + tokenTargetContractId = regTokenTarget.contractId + tokenTargetId = tokenIdFromBytes(tokenTargetContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + // Register V Stable Swap Contract + description <- validDescStringGen + initVStableSwapDataStack <- initVStableSwapDataStackGen(tokenBaseId.arr, tokenTargetId.arr, maxOrderPerUser, unitPriceBase, unitPriceTarget) + regVStableSwapContract <- registerVStableSwapGen(master, vStableSwapContract, initVStableSwapDataStack, description, fee, ts + 2) + // Issue base token + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issueTokenBase <- issueToken(master, tokenBaseContractId, issueAmountBase, fee, ts + 3) + // Issue target token + issueTokenTarget <- issueToken(master, tokenTargetContractId, issueAmountTarget, fee, ts + 4) + // Deposit base and target token into V Stable Swap + depositBase <- depositToken(master, tokenBaseContractId, master.toAddress.bytes.arr, regVStableSwapContract.contractId.bytes.arr, issueAmountBase, fee, ts + 5) + depositTarget <- depositToken(master, tokenTargetContractId, master.toAddress.bytes.arr, regVStableSwapContract.contractId.bytes.arr, issueAmountTarget, fee, ts + 6) + } yield (genesis, genesis2, master, user, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) +} From 03b4ed595c45fb8f2846d842a62e96639719349c Mon Sep 17 00:00:00 2001 From: twwu123 Date: Mon, 1 Feb 2021 16:03:02 +0800 Subject: [PATCH 230/391] Add tests for depositing and withdrawing tokens for V Stable Swap Contract --- .../ExecuteVStableSwapValidDiffTest.scala | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala new file mode 100644 index 000000000..d9f08a3de --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala @@ -0,0 +1,82 @@ +package vsys.blockchain.state.contract.vstableswap + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.token.SystemContractGen +import vsys.blockchain.contract.vstableswap.{VStableSwapContractGen, VStableSwapFunctionHelperGen} +import vsys.blockchain.state._ +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction => EC, RegisterContractTransaction => RC} +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} + +class ExecuteVStableSwapValidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with SystemContractGen + with VStableSwapContractGen + with VStableSwapFunctionHelperGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndVStableSwapDepositToken: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC)] = for { + (genesis, _, _, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, _, _, _) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget) + + property("V Stable Swap able to deposit") { + forAll(preconditionsAndVStableSwapDepositToken) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase))), + TestBlock.createWithTxStatus(depositBase.timestamp, Seq(depositBase), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueTarget))), + TestBlock.createWithTxStatus(depositBase.timestamp, Seq(depositTarget), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVStableSwapWithdrawToken: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, _) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + withdrawBase <- withdrawToken(master, regTokenBase.contractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 1000, fee, ts + 7) + withdrawTarget <- withdrawToken(master, regTokenTarget.contractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 1000, fee, ts + 8) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, withdrawBase, withdrawTarget) + + property("V Stable Swap able to withdraw") { + forAll(preconditionsAndVStableSwapWithdrawToken) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, withdrawBase: EC, withdrawTarget: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBase.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), + TestBlock.createWithTxStatus(withdrawBase.timestamp, Seq(withdrawBase), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueTarget, depositTarget))), + TestBlock.createWithTxStatus(withdrawTarget.timestamp, Seq(withdrawTarget), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } +} From 3d88363e47e9e603b1fae1f694f5e09eda6bf7b4 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Mon, 1 Feb 2021 16:39:16 +0800 Subject: [PATCH 231/391] Improve check for same target and base token --- .../contract/ContractVStableSwap.scala | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 3c56f7925..8738ec58d 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -90,7 +90,7 @@ object ContractVStableSwap { val depositId: Short = 1 val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId") ++ Seq("baseTokenId", "targetTokenId", "isValidTokenId", - "isBaseToken", "baseTokenIfBlock", "isTargetToken", "valueFalse", "targetTokenIfBlock") + "isBaseToken", "valueFalse", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock") val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) val depositTriggerOpcs: Seq[Array[Byte]] = Seq( assertCaller ++ Array(0.toByte), @@ -98,23 +98,24 @@ object ContractVStableSwap { cdbvrGet ++ Array(targetTokenIdStateVar.index, 4.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), compareBytesEqual ++ Array(2.toByte, 3.toByte, 6.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(5.toByte, 7.toByte), cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(7.toByte), - compareBytesEqual ++ Array(2.toByte, 4.toByte, 8.toByte), - basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(9.toByte), + ), DataType.OpcBlock).bytes ++ Array(8.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 9.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( - assertEqual ++ Array(5.toByte, 9.toByte), + assertEqual ++ Array(5.toByte, 7.toByte), cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) ), DataType.OpcBlock).bytes ++ Array(10.toByte), - conditionIf ++ Array(6.toByte, 7.toByte), - conditionIf ++ Array(8.toByte, 10.toByte), + conditionIf ++ Array(6.toByte, 8.toByte), + conditionIf ++ Array(9.toByte, 10.toByte), assertTrue ++ Array(5.toByte) ) lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) @@ -124,7 +125,7 @@ object ContractVStableSwap { val withdrawId: Short = 2 val withdrawPara: Seq[String] = Seq("withdrawer", "amount", "tokenId") ++ Seq("baseTokenId", "targetTokenId", "isValidTokenId", - "isBaseToken", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock") + "isBaseToken", "valueFalse", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock") val withdrawDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) val withdrawTriggerOpcs: Seq[Array[Byte]] = Seq( assertCaller ++ Array(0.toByte), @@ -132,21 +133,24 @@ object ContractVStableSwap { cdbvrGet ++ Array(targetTokenIdStateVar.index, 4.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), compareBytesEqual ++ Array(2.toByte, 3.toByte, 6.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(5.toByte, 7.toByte), cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(7.toByte), - compareBytesEqual ++ Array(2.toByte, 4.toByte, 8.toByte), + ), DataType.OpcBlock).bytes ++ Array(8.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 9.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(5.toByte, 7.toByte), cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(9.toByte), - conditionIf ++ Array(6.toByte, 7.toByte), - conditionIf ++ Array(8.toByte, 9.toByte), + ), DataType.OpcBlock).bytes ++ Array(10.toByte), + conditionIf ++ Array(6.toByte, 8.toByte), + conditionIf ++ Array(9.toByte, 10.toByte), assertTrue ++ Array(5.toByte) ) lazy val withdrawTrigger: Array[Byte] = getFunctionBytes(withdrawId, onWithDrawTriggerType, nonReturnType, withdrawDataType, withdrawTriggerOpcs) From ea59144c8201630c2bf12fe48ed98a1e39d6ebbd Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 2 Feb 2021 10:27:08 +0800 Subject: [PATCH 232/391] Add test for supersede and set order for V Stable Swap contract --- .../vstableswap/VStableSwapContractGen.scala | 5 ++++ .../ExecuteVStableSwapValidDiffTest.scala | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala index 05117d5b9..a45e00e4f 100644 --- a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala @@ -130,6 +130,11 @@ trait VStableSwapContractGen { unitPriceTarget <- Gen.const(DataEntry.create(Longs.toByteArray(unitPriceTarget), DataType.Amount).right.get) } yield Seq(baseTokenId, targetTokenId, maxOrderPerUser, unitPriceBase, unitPriceTarget) + def supersedeVStableSwapGen(signer: PrivateKeyAccount, contractId: ContractAccount, newAdd: Address, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { + data: Seq[DataEntry] <- addressDataStackGen(newAdd) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, supersedeIndex, data, attachment, fee, feeScale, ts).explicitGet() + def setOrderVStableSwapGen(sender: PrivateKeyAccount, contractId: ContractAccount, feeBase: Long, diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala index d9f08a3de..65afe2ef9 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala @@ -79,4 +79,30 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec } } } + + val preconditionsAndVStableSwapSupersedeAndSetOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, genesis2, master, user, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + supersede <- supersedeVStableSwapGen(master, regVStableSwapContract.contractId, user.toAddress, attach, fee, ts + 5) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 1000, 1000, attach, fee, ts + 6) + } yield(genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, supersede, setOrder) + + property("V Stable Swap able to supersede and set order") { + forAll(preconditionsAndVStableSwapSupersedeAndSetOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, supersede: EC, setOrder: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBase.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, supersede))), + TestBlock.createWithTxStatus(setOrder.timestamp, Seq(setOrder), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } } From d0389865a493afe51efab09b44c5e649186c7ffb Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 2 Feb 2021 10:53:09 +0800 Subject: [PATCH 233/391] Fix update function in function generator --- .../vstableswap/VStableSwapContractGen.scala | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala index a45e00e4f..ece74cf12 100644 --- a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala @@ -65,14 +65,18 @@ trait VStableSwapContractGen { feeTarget: Long, minBase: Long, minTarget: Long, - maxTarget: Long): Gen[Seq[DataEntry]] = for { + maxTarget: Long, + priceBase: Long, + priceTarget: Long): Gen[Seq[DataEntry]] = for { orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) feeBase <- Gen.const(DataEntry(Longs.toByteArray(feeBase), DataType.Amount)) feeTarget <- Gen.const(DataEntry(Longs.toByteArray(feeTarget), DataType.Amount)) minBase <- Gen.const(DataEntry(Longs.toByteArray(minBase), DataType.Amount)) minTarget <- Gen.const(DataEntry(Longs.toByteArray(minTarget), DataType.Amount)) maxTarget <- Gen.const(DataEntry(Longs.toByteArray(maxTarget), DataType.Amount)) - } yield Seq(orderId, feeBase, feeTarget, minBase, minTarget, maxTarget) + priceBase <- Gen.const(DataEntry(Longs.toByteArray(priceBase), DataType.Amount)) + priceTarget <- Gen.const(DataEntry(Longs.toByteArray(priceTarget), DataType.Amount)) + } yield Seq(orderId, feeBase, feeTarget, minBase, minTarget, maxTarget, priceBase, priceTarget) def orderDepositDataStackGen(orderId: Array[Byte], baseDeposit: Long, @@ -165,12 +169,14 @@ trait VStableSwapContractGen { minBase: Long, minTarget: Long, maxTarget: Long, + priceBase: Long, + priceTarget: Long, attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = updateIndex for { - data: Seq[DataEntry] <- updateDataStackGen(orderId, feeBase, feeTarget, minBase, minTarget, maxTarget) + data: Seq[DataEntry] <- updateDataStackGen(orderId, feeBase, feeTarget, minBase, minTarget, maxTarget, priceBase, priceTarget) } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } From b5ca67c257d902728d01f658779a8ba3a0fd6bdf Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 2 Feb 2021 12:01:41 +0800 Subject: [PATCH 234/391] add contract temp --- .../blockchain/contract/ContractVEscrow.scala | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala new file mode 100644 index 000000000..8f684121e --- /dev/null +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -0,0 +1,29 @@ +package vsys.blockchain.contract + +import com.google.common.primitives.{Ints} +import vsys.blockchain.state._ +import vsys.utils.serialization.Deser + +object ContractVEscrow { + lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(), + Seq(), + Seq(), + Seq(), + Seq() + ).explicitGet() + + // State Var + + // State Map + + // Initialization Trigger + + // Deposit Trigger + + // WithDraw Trigger + + // Functions + + // Textual +} \ No newline at end of file From 913ef28a144bf5e47e5f25f3383c1cc6e6ca9d75 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 2 Feb 2021 12:07:07 +0800 Subject: [PATCH 235/391] add state var --- .../vsys/blockchain/contract/ContractVEscrow.scala | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 8f684121e..cb29d0656 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -1,6 +1,7 @@ package vsys.blockchain.contract -import com.google.common.primitives.{Ints} +import com.google.common.primitives.Ints +import vsys.blockchain.contract.ContractGen.StateVar import vsys.blockchain.state._ import vsys.utils.serialization.Deser @@ -14,6 +15,15 @@ object ContractVEscrow { ).explicitGet() // State Var + val stateVarName = List("maker", "judge", "tokenId", "duration", "judgeDuration") + val makerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) + val judgeStateVar: StateVar = StateVar(1.toByte, DataType.Address.id.toByte) + val tokenIdStateVar: StateVar = StateVar(2.toByte, DataType.TokenId.id.toByte) + val durationStateVar: StateVar = StateVar(3.toByte, DataType.Timestamp.id.toByte) + val judgeDurationStateVar: StateVar = StateVar(4.toByte, DataType.Timestamp.id.toByte) + lazy val stateVarSeq = Seq(makerStateVar.arr, judgeStateVar.arr, tokenIdStateVar.arr, + durationStateVar.arr, judgeDurationStateVar.arr) + lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map From 9d4b29b8707c8fb8db4f4243146f7a7f30dee4c0 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 2 Feb 2021 15:33:07 +0800 Subject: [PATCH 236/391] Fix bugs - order ID use Data Entry create function for data stack generation --- .../vstableswap/VStableSwapContractGen.scala | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala index ece74cf12..91c9263d9 100644 --- a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala @@ -64,24 +64,26 @@ trait VStableSwapContractGen { feeBase: Long, feeTarget: Long, minBase: Long, + maxBase: Long, minTarget: Long, maxTarget: Long, priceBase: Long, priceTarget: Long): Gen[Seq[DataEntry]] = for { - orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) feeBase <- Gen.const(DataEntry(Longs.toByteArray(feeBase), DataType.Amount)) feeTarget <- Gen.const(DataEntry(Longs.toByteArray(feeTarget), DataType.Amount)) minBase <- Gen.const(DataEntry(Longs.toByteArray(minBase), DataType.Amount)) + maxBase <- Gen.const(DataEntry(Longs.toByteArray(maxBase), DataType.Amount)) minTarget <- Gen.const(DataEntry(Longs.toByteArray(minTarget), DataType.Amount)) maxTarget <- Gen.const(DataEntry(Longs.toByteArray(maxTarget), DataType.Amount)) priceBase <- Gen.const(DataEntry(Longs.toByteArray(priceBase), DataType.Amount)) priceTarget <- Gen.const(DataEntry(Longs.toByteArray(priceTarget), DataType.Amount)) - } yield Seq(orderId, feeBase, feeTarget, minBase, minTarget, maxTarget, priceBase, priceTarget) + } yield Seq(orderId, feeBase, feeTarget, minBase, maxBase, minTarget, maxTarget, priceBase, priceTarget) def orderDepositDataStackGen(orderId: Array[Byte], baseDeposit: Long, targetDeposit: Long): Gen[Seq[DataEntry]] = for { - orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) baseDeposit <- Gen.const(DataEntry(Longs.toByteArray(baseDeposit), DataType.Amount)) targetDeposit <- Gen.const(DataEntry(Longs.toByteArray(targetDeposit), DataType.Amount)) } yield Seq(orderId, baseDeposit, targetDeposit) @@ -89,7 +91,7 @@ trait VStableSwapContractGen { def orderWithdrawDataStackGen(orderId: Array[Byte], baseWithdraw: Long, targetWithdraw: Long): Gen[Seq[DataEntry]] = for { - orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) baseWithdraw <- Gen.const(DataEntry(Longs.toByteArray(baseWithdraw), DataType.Amount)) targetWithdraw <- Gen.const(DataEntry(Longs.toByteArray(targetWithdraw), DataType.Amount)) } yield Seq(orderId, baseWithdraw, targetWithdraw) @@ -103,7 +105,7 @@ trait VStableSwapContractGen { fee: Long, price: Long, deadLine: Long): Gen[Seq[DataEntry]] = for { - orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) amount <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) fee <- Gen.const(DataEntry(Longs.toByteArray(fee), DataType.Amount)) price <- Gen.const(DataEntry(Longs.toByteArray(price), DataType.Amount)) @@ -115,7 +117,7 @@ trait VStableSwapContractGen { fee: Long, price: Long, deadLine: Long): Gen[Seq[DataEntry]] = for { - orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) amount <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) fee <- Gen.const(DataEntry(Longs.toByteArray(fee), DataType.Amount)) price <- Gen.const(DataEntry(Longs.toByteArray(price), DataType.Amount)) @@ -127,11 +129,11 @@ trait VStableSwapContractGen { maxOrderPerUser: Long, unitPriceBase: Long, unitPriceTarget: Long): Gen[Seq[DataEntry]] = for { - baseTokenId <- Gen.const(DataEntry.create(baseTokenId, DataType.TokenId).right.get) - targetTokenId <- Gen.const(DataEntry.create(targetTokenId, DataType.TokenId).right.get) - maxOrderPerUser <- Gen.const(DataEntry.create(Longs.toByteArray(maxOrderPerUser), DataType.Amount).right.get) - unitPriceBase <- Gen.const(DataEntry.create(Longs.toByteArray(unitPriceBase), DataType.Amount).right.get) - unitPriceTarget <- Gen.const(DataEntry.create(Longs.toByteArray(unitPriceTarget), DataType.Amount).right.get) + baseTokenId <- Gen.const(DataEntry(baseTokenId, DataType.TokenId)) + targetTokenId <- Gen.const(DataEntry(targetTokenId, DataType.TokenId)) + maxOrderPerUser <- Gen.const(DataEntry(Longs.toByteArray(maxOrderPerUser), DataType.Amount)) + unitPriceBase <- Gen.const(DataEntry(Longs.toByteArray(unitPriceBase), DataType.Amount)) + unitPriceTarget <- Gen.const(DataEntry(Longs.toByteArray(unitPriceTarget), DataType.Amount)) } yield Seq(baseTokenId, targetTokenId, maxOrderPerUser, unitPriceBase, unitPriceTarget) def supersedeVStableSwapGen(signer: PrivateKeyAccount, contractId: ContractAccount, newAdd: Address, @@ -167,6 +169,7 @@ trait VStableSwapContractGen { feeBase: Long, feeTarget: Long, minBase: Long, + maxBase: Long, minTarget: Long, maxTarget: Long, priceBase: Long, @@ -176,7 +179,7 @@ trait VStableSwapContractGen { ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = updateIndex for { - data: Seq[DataEntry] <- updateDataStackGen(orderId, feeBase, feeTarget, minBase, minTarget, maxTarget, priceBase, priceTarget) + data: Seq[DataEntry] <- updateDataStackGen(orderId, feeBase, feeTarget, minBase, maxBase, minTarget, maxTarget, priceBase, priceTarget) } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } From d8c90414c03f0dd4a3a5a4e091396181aada1d00 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Wed, 3 Feb 2021 10:34:23 +0800 Subject: [PATCH 237/391] Add Withdraw and set order Invalid Unit Test Cases --- .../vstableswap/VStableSwapContractGen.scala | 2 +- .../ExecuteVStableSwapInvalidDiffTest.scala | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala index 91c9263d9..a716d76e0 100644 --- a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapContractGen.scala @@ -97,7 +97,7 @@ trait VStableSwapContractGen { } yield Seq(orderId, baseWithdraw, targetWithdraw) def closeDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { - orderId <- Gen.const(DataEntry(orderId, DataType.ShortBytes)) + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) } yield Seq(orderId) def swapBaseToTargetDataStackGen(orderId: Array[Byte], diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala new file mode 100644 index 000000000..79284ff1a --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala @@ -0,0 +1,70 @@ +package test.scala.vsys.blockchain.state.contract.vstableswap + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.token.SystemContractGen +import vsys.blockchain.contract.vstableswap.{VStableSwapContractGen, VStableSwapFunctionHelperGen} +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction => EC, RegisterContractTransaction => RC} +import vsys.blockchain.state._ + +class ExecuteVStableSwapInvalidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with SystemContractGen + with VStableSwapContractGen + with VStableSwapFunctionHelperGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndVStableSwapDepositToken: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, _, depositBase, _, fee, ts, _) + <- createBaseTokenTargetTokenAndInitVStableSwap(1000, 1, 1000, 1000, + 1, 1000, 5, 1, 1) + withdrawBase <- withdrawToken(master, regTokenBase.contractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 100, fee, ts+7) + withdrawBaseInvalid <- withdrawToken(master, regTokenBase.contractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 10000, fee, ts+7) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, depositBase, withdrawBase, withdrawBaseInvalid) + + property("unable to withdraw tokens") { + forAll(preconditionsAndVStableSwapDepositToken) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, depositBase: EC, withdrawBase: EC, withdrawBaseInvalid: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), + TestBlock.createWithTxStatus(withdrawBase.timestamp, Seq(withdrawBase), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), + TestBlock.createWithTxStatus(withdrawBaseInvalid.timestamp, Seq(withdrawBaseInvalid), TransactionStatus.ContractTokenBalanceInsufficient)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient + } + } + } + + val preconditionsAndVStableSwapSetOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attachment) + <- createBaseTokenTargetTokenAndInitVStableSwap(1000, 1, 1000, 1000, + 1, 1000, 5, 1, 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 1000, 1000, attachment, fee, ts+7) + setOrderInvalid <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 10000, 1000, attachment, fee, ts+7) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, setOrderInvalid) + + property("unable to set order") { + forAll(preconditionsAndVStableSwapSetOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, setOrderInvalid: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget))), + TestBlock.createWithTxStatus(setOrder.timestamp, Seq(setOrder), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // deposit into contract is less than deposit into order + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget))), + TestBlock.createWithTxStatus(setOrderInvalid.timestamp, Seq(setOrderInvalid), TransactionStatus.ContractMapValueInsufficient)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + } + } + +} From f9cfdd5b87adbdd53cf2cdd6070e1f937616965b Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Wed, 3 Feb 2021 10:35:27 +0800 Subject: [PATCH 238/391] Add update order Invalid Unit Test Cases --- .../ExecuteVStableSwapInvalidDiffTest.scala | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala index 79284ff1a..61f1b5392 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala @@ -67,4 +67,29 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec } } + val preconditionsAndVStableSwapUpdateOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attachment) + <- createBaseTokenTargetTokenAndInitVStableSwap(1000, 1, 1000, 1000, + 1, 1000, 5, 1, 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 1000, 1000, attachment, fee, ts+7) + updateOrder <- updateVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 0, 0, 10, 1000, 10, 1000, 10, 10, attachment, fee, ts+8) + updateOrderInvalid <- updateVStableSwapGen(master, regVStableSwapContract.contractId, Array[Byte](10), 0, 0, 10, 1000, 10, 1000, 10, 10, attachment, fee, ts+8) + + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, updateOrder, updateOrderInvalid) + + property("unable to update order") { + forAll(preconditionsAndVStableSwapUpdateOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, updateOrder: EC, updateOrderInvalid: EC) => + + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(updateOrder.timestamp, Seq(updateOrder), TransactionStatus.Success)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success + } + + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(updateOrderInvalid.timestamp, Seq(updateOrderInvalid), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined + } + } + } } From a0c0d98fac9905e669cbef0501b5aaf5662a0305 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 4 Feb 2021 15:52:26 +0800 Subject: [PATCH 239/391] add state map --- .../blockchain/contract/ContractVEscrow.scala | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index cb29d0656..1251c922e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -1,7 +1,7 @@ package vsys.blockchain.contract import com.google.common.primitives.Ints -import vsys.blockchain.contract.ContractGen.StateVar +import vsys.blockchain.contract.ContractGen.{StateMap, StateVar, textualStateMap} import vsys.blockchain.state._ import vsys.utils.serialization.Deser @@ -26,7 +26,55 @@ object ContractVEscrow { lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map + val stateMapContractBalance = List("contractBalance", "userAddress", "balance") + val stateMapOrderPayer = List("orderPayer", "orderId", "payer") + val stateMapOrderRecipient = List("orderRecipient", "orderId", "recipient") + val stateMapOrderAmount = List("orderAmount", "orderId", "amount") + val stateMapOrderRecipientDeposit = List("orderRecipientDeposit", "orderId", "repDeposit") + val stateMapOrderJudgeDeposit = List("orderJudgeDeposit", "orderId", "judgeDeposit") + val stateMapOrderFee = List("orderFee", "orderId", "fee") + val stateMapOrderRecipientAmount = List("orderRecipientAmount", "orderId", "repAmount") + val stateMapOrderRefund = List("orderRefund", "orderId", "refund") + val stateMapOrderRecipientRefund = List("orderRecipientRefund", "orderId", "repRefund") + val stateMapOrderExpirationTime = List("orderExpirationTime", "orderId", "expirationTime") + val stateMapOrderStatus = List("orderStatus", "orderId", "status") + val stateMapOrderRepDepositStatus = List("orderRepDepositStatus", "orderId", "repDepositStatus") + val stateMapOrderJudgeDepositStatus = List("orderJudgeDepositStatus", "orderId", "judgeDepositStatus") + val stateMapOrderSubmitStatus = List("orderSubmitStatus", "orderId", "submitStatus") + val stateMapOrderJudgeStatus = List("orderJudgeStatus", "orderId", "judgeStatus") + val stateMapOrderRepLockedAmount = List("orderRepLockedAmount", "orderId", "repLockedAmount") + val stateMapOrderJudgeLockedAmount = List("orderJudgeLockedAmount", "orderId", "judgeLockedAmount") + val contractBalanceMap: StateMap = StateMap(0.toByte, DataType.Address.id.toByte, DataType.Amount.id.toByte) + val orderPayerMap: StateMap = StateMap(1.toByte, DataType.ShortBytes.id.toByte, DataType.Address.id.toByte) + val orderRecipientMap: StateMap = StateMap(2.toByte, DataType.ShortBytes.id.toByte, DataType.Address.id.toByte) + val orderAmountMap: StateMap = StateMap(3.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderRecipientDepositMap: StateMap = StateMap(4.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderJudgeDepositMap: StateMap = StateMap(5.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderFeeMap: StateMap = StateMap(6.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderRecipientAmountMap: StateMap = StateMap(7.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderRefundMap: StateMap = StateMap(8.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderRecipientRefundMap: StateMap = StateMap(9.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderExpirationTimeMap: StateMap = StateMap(10.toByte, DataType.ShortBytes.id.toByte, DataType.Timestamp.id.toByte) + val orderStatusMap: StateMap = StateMap(11.toByte, DataType.ShortBytes.id.toByte, DataType.Boolean.id.toByte) + val orderRepDepositStatusMap: StateMap = StateMap(12.toByte, DataType.ShortBytes.id.toByte, DataType.Boolean.id.toByte) + val orderJudgeDepositStatusMap: StateMap = StateMap(13.toByte, DataType.ShortBytes.id.toByte, DataType.Boolean.id.toByte) + val orderSubmitStatusMap: StateMap = StateMap(14.toByte, DataType.ShortBytes.id.toByte, DataType.Boolean.id.toByte) + val orderJudgeStatusMap: StateMap = StateMap(15.toByte, DataType.ShortBytes.id.toByte, DataType.Boolean.id.toByte) + val orderRepLockedAmountMap: StateMap = StateMap(16.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + val orderJudgeLockedAmountMap: StateMap = StateMap(17.toByte, DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte) + lazy val stateMapSeq = Seq(contractBalanceMap.arr, orderPayerMap.arr, orderRecipientMap.arr, orderAmountMap.arr, + orderRecipientDepositMap.arr, orderJudgeDepositMap.arr, orderFeeMap.arr, + orderRecipientAmountMap.arr, orderRefundMap.arr, orderRecipientRefundMap.arr, + orderExpirationTimeMap.arr, orderStatusMap.arr, orderRepDepositStatusMap.arr, orderJudgeDepositStatusMap.arr, + orderSubmitStatusMap.arr, orderJudgeStatusMap.arr, orderRepLockedAmountMap.arr, orderJudgeLockedAmountMap.arr) + lazy val stateMapTextual: Array[Byte] = textualStateMap( + Seq(stateMapContractBalance, stateMapOrderPayer, stateMapOrderRecipient, stateMapOrderAmount, + stateMapOrderRecipientDeposit, stateMapOrderJudgeDeposit, stateMapOrderFee, stateMapOrderRecipientAmount, + stateMapOrderRefund, stateMapOrderRecipientRefund, stateMapOrderExpirationTime, stateMapOrderStatus, + stateMapOrderRepDepositStatus, stateMapOrderJudgeDepositStatus, stateMapOrderSubmitStatus, stateMapOrderJudgeStatus, + stateMapOrderRepLockedAmount, stateMapOrderJudgeLockedAmount)) + // Initialization Trigger // Deposit Trigger From e18622e2bc9c3f75f6f68e9171c592b1e57b61e5 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 4 Feb 2021 15:54:57 +0800 Subject: [PATCH 240/391] Add Order Deposit and Order Withdraw Invalid Unit Test Cases --- .../ExecuteVStableSwapInvalidDiffTest.scala | 80 ++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala index 61f1b5392..f10b60525 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala @@ -1,4 +1,4 @@ -package test.scala.vsys.blockchain.state.contract.vstableswap +package vsys.blockchain.state.contract.vstableswap import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} @@ -37,6 +37,7 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(withdrawBase.timestamp, Seq(withdrawBase), TransactionStatus.Success)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } + // withdraw tokens more than depositing in vstable swap contract assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), TestBlock.createWithTxStatus(withdrawBaseInvalid.timestamp, Seq(withdrawBaseInvalid), TransactionStatus.ContractTokenBalanceInsufficient)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient @@ -85,11 +86,86 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(updateOrder.timestamp, Seq(updateOrder), TransactionStatus.Success)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success } - + // update order with wrong order id assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(updateOrderInvalid.timestamp, Seq(updateOrderInvalid), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined } } } + + val preconditionsAndVStableSwapOrderDeposit: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attachment) + <- createBaseTokenTargetTokenAndInitVStableSwap(1000, 1, 1000, 1000, + 1, 1000, 5, 1, 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 990, 990, attachment, fee, ts+7) + closeOrder <- closeVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, attachment, fee, ts+8) + orderDeposit <- orderDepositVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10, 10, attachment, fee, ts+9) + orderDepositInvalid <- orderDepositVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10000, 10, attachment, fee, ts+9) + orderDepositInvalid2 <- orderDepositVStableSwapGen(master, regVStableSwapContract.contractId, Array[Byte](10), 10, 10, attachment, fee, ts+9) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, closeOrder, orderDeposit, orderDepositInvalid, orderDepositInvalid2) + + property("unable to order deposit") { + forAll(preconditionsAndVStableSwapOrderDeposit) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, closeOrder: EC, orderDeposit: EC, orderDepositInvalid: EC, orderDepositInvalid2: EC) => + + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderDeposit.timestamp, Seq(orderDeposit), TransactionStatus.Success)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success + } + // deposit into order is greater than deposit into contract + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderDepositInvalid.timestamp, Seq(orderDepositInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // order deposit with wrong order id + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderDepositInvalid2.timestamp, Seq(orderDepositInvalid2), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined + } + // order deposit after order close + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), + TestBlock.createWithTxStatus(orderDeposit.timestamp, Seq(orderDeposit), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsAndVStableSwapOrderWithdraw: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attachment) + <- createBaseTokenTargetTokenAndInitVStableSwap(1000, 1, 1000, 1000, + 1, 1000, 5, 1, 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 990, 990, attachment, fee, ts+7) + closeOrder <- closeVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, attachment, fee, ts+8) + orderWithdraw <- orderWithdrawVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10, 10, attachment, fee, ts+9) + orderWithdrawInvalid <- orderWithdrawVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10000, 10, attachment, fee, ts+9) + orderWithdrawInvalid2 <- orderWithdrawVStableSwapGen(master, regVStableSwapContract.contractId, Array[Byte](10), 10, 10, attachment, fee, ts+9) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, closeOrder, orderWithdraw, orderWithdrawInvalid, orderWithdrawInvalid2) + + property("unable to order withdraw") { + forAll(preconditionsAndVStableSwapOrderWithdraw) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, closeOrder: EC, orderWithdraw: EC, orderWithdrawInvalid: EC, orderWithdrawInvalid2: EC) => + + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderWithdraw.timestamp, Seq(orderWithdraw), TransactionStatus.Success)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success + } + // withdraw from contract is greater than deposit into order + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderWithdrawInvalid.timestamp, Seq(orderWithdrawInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + + // order withdraw with wrong order id + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderWithdrawInvalid2.timestamp, Seq(orderWithdrawInvalid2), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined + } + // order withdraw after order close + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), + TestBlock.createWithTxStatus(orderWithdraw.timestamp, Seq(orderWithdraw), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } } From 114d788018f423959b5d6f8b832b2f0c860b8779 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 4 Feb 2021 15:57:01 +0800 Subject: [PATCH 241/391] Add Close Order Invalid Unit Test Cases --- .../ExecuteVStableSwapInvalidDiffTest.scala | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala index f10b60525..bcb452290 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala @@ -168,4 +168,28 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec } } } + + val preconditionsAndVStableSwapOrderClose: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attachment) + <- createBaseTokenTargetTokenAndInitVStableSwap(1000, 1, 1000, 1000, + 1, 1000, 5, 1, 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 1000, 1000, attachment, fee, ts+7) + closeOrder <- closeVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, attachment, fee, ts+8) + closeOrderInvalid <- closeVStableSwapGen(master, regVStableSwapContract.contractId, Array[Byte](10), attachment, fee, ts+8) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, closeOrder, closeOrderInvalid) + + property("unable to close order") { + forAll(preconditionsAndVStableSwapOrderClose) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, closeOrder: EC, closeOrderInvalid: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(closeOrder.timestamp, Seq(closeOrder), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // close order with wrong order id + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(closeOrderInvalid.timestamp, Seq(closeOrderInvalid), TransactionStatus.ContractStateMapNotDefined)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined + } + } + } } From 02d8128298c947f8a7b50b55a967bb7f923bca8c Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 4 Feb 2021 15:58:58 +0800 Subject: [PATCH 242/391] Add Base To Target Invalid Unit Test Cases --- .../ExecuteVStableSwapInvalidDiffTest.scala | 96 +++++++++++++++++-- 1 file changed, 90 insertions(+), 6 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala index bcb452290..b43ed71cc 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala @@ -68,20 +68,20 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec } } - val preconditionsAndVStableSwapUpdateOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC)] = for { + val preconditionsAndVStableSwapUpdateOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attachment) <- createBaseTokenTargetTokenAndInitVStableSwap(1000, 1, 1000, 1000, 1, 1000, 5, 1, 1) setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 1000, 1000, attachment, fee, ts+7) - updateOrder <- updateVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 0, 0, 10, 1000, 10, 1000, 10, 10, attachment, fee, ts+8) - updateOrderInvalid <- updateVStableSwapGen(master, regVStableSwapContract.contractId, Array[Byte](10), 0, 0, 10, 1000, 10, 1000, 10, 10, attachment, fee, ts+8) + closeOrder <- closeVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, attachment, fee, ts+8) + updateOrder <- updateVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 0, 0, 10, 1000, 10, 1000, 10, 10, attachment, fee, ts+9) + updateOrderInvalid <- updateVStableSwapGen(master, regVStableSwapContract.contractId, Array[Byte](10), 0, 0, 10, 1000, 10, 1000, 10, 10, attachment, fee, ts+9) - } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, updateOrder, updateOrderInvalid) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, closeOrder, updateOrder, updateOrderInvalid) property("unable to update order") { forAll(preconditionsAndVStableSwapUpdateOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, - regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, updateOrder: EC, updateOrderInvalid: EC) => - + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, closeOrder: EC, updateOrder: EC, updateOrderInvalid: EC) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(updateOrder.timestamp, Seq(updateOrder), TransactionStatus.Success)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success @@ -91,6 +91,11 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(updateOrderInvalid.timestamp, Seq(updateOrderInvalid), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined } + // update order after close order + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), + TestBlock.createWithTxStatus(updateOrder.timestamp, Seq(updateOrder), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } } } @@ -192,4 +197,83 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec } } } + val preconditionsAndVStableSwapBaseToTarget: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attachment) + <- createBaseTokenTargetTokenAndInitVStableSwap(Long.MaxValue, 1, Long.MaxValue, Long.MaxValue, + 1, Long.MaxValue, 5, 1, 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 1, 990, 100000, attachment, fee, ts+7) + setOrder1 <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 1, 990, 10, attachment, fee, ts+7) + setOrder2 <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, Long.MaxValue, 10, 1000, 1, 1, 990, Long.MaxValue, attachment, fee, ts+7) + closeOrder <- closeVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, attachment, fee, ts+8) + swapBaseToTarget <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10, 0, 10, ts+100, attachment, fee, ts+9) + swapBaseToTargetInvalid <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10, 0, 20, ts+100, attachment, fee, ts+9) + swapBaseToTargetInvalid2 <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10, 10, 10, ts+100, attachment, fee, ts+9) + swapBaseToTargetInvalid3 <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder1.id.arr, 10, 0, 10, ts+100, attachment, fee, ts+9) + swapBaseToTargetInvalid4 <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder2.id.arr, Long.MaxValue, 0, 1, ts+100, attachment, fee, ts+9) + swapBaseToTargetInvalid5 <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10, 0, 10, ts-100, attachment, fee, ts+9) + swapBaseToTargetInvalid6 <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10000, 0, 10, ts+100, attachment, fee, ts+9) + swapBaseToTargetInvalid7 <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 1, 0, 10, ts+100, attachment, fee, ts+9) + swapBaseToTargetInvalid8 <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, Array[Byte](10), 10, 0, 10, ts+100, attachment, fee, ts+9) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, setOrder1, setOrder2, closeOrder, swapBaseToTarget, swapBaseToTargetInvalid, swapBaseToTargetInvalid2, + swapBaseToTargetInvalid3, swapBaseToTargetInvalid4, swapBaseToTargetInvalid5, swapBaseToTargetInvalid6, swapBaseToTargetInvalid7, swapBaseToTargetInvalid8) + + property("unable to swap base to target") { + forAll(preconditionsAndVStableSwapBaseToTarget) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, setOrder1: EC, setOrder2: EC, closeOrder: EC, swapBaseToTarget: EC, swapBaseToTargetInvalid: EC, swapBaseToTargetInvalid2: EC, + swapBaseToTargetInvalid3: EC, swapBaseToTargetInvalid4: EC, swapBaseToTargetInvalid5: EC, swapBaseToTargetInvalid6: EC, swapBaseToTargetInvalid7: EC, swapBaseToTargetInvalid8: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(swapBaseToTarget.timestamp, Seq(swapBaseToTarget), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + // price is not equal to priceBase + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(swapBaseToTargetInvalid.timestamp, Seq(swapBaseToTargetInvalid), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // swapFee is not equal to baseFee + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(swapBaseToTargetInvalid2.timestamp, Seq(swapBaseToTargetInvalid2), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // swap base token with not enough depositing target token + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder1))), + TestBlock.createWithTxStatus(swapBaseToTargetInvalid3.timestamp, Seq(swapBaseToTargetInvalid3), TransactionStatus.ContractMapValueInsufficient)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // swap base token with not enough holding base token + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder2))), + TestBlock.createWithTxStatus(swapBaseToTargetInvalid4.timestamp, Seq(swapBaseToTargetInvalid4), TransactionStatus.ContractMapValueInsufficient)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + // swap base token with wrong deadline + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), + TestBlock.create(setOrder.timestamp, Seq(setOrder))), + TestBlock.createWithTxStatus(swapBaseToTargetInvalid5.timestamp, Seq(swapBaseToTargetInvalid5), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // swap base token more than maxBase + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), + TestBlock.create(setOrder.timestamp, Seq(setOrder))), + TestBlock.createWithTxStatus(swapBaseToTargetInvalid6.timestamp, Seq(swapBaseToTargetInvalid6), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // swap base token less than minBase + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), + TestBlock.create(setOrder.timestamp, Seq(setOrder))), + TestBlock.createWithTxStatus(swapBaseToTargetInvalid7.timestamp, Seq(swapBaseToTargetInvalid7), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // swap base token with wrong order id + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), + TestBlock.create(setOrder.timestamp, Seq(setOrder))), + TestBlock.createWithTxStatus(swapBaseToTargetInvalid8.timestamp, Seq(swapBaseToTargetInvalid8), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined + } + // swap base token after order close + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), + TestBlock.createWithTxStatus(swapBaseToTarget.timestamp, Seq(swapBaseToTarget), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } } From 33a545bf9fa6f1e15385122b66c756b4fe79f315 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 4 Feb 2021 17:06:08 +0800 Subject: [PATCH 243/391] Add maxOrderPerUser Invalid Unit Test Cases and fix code styles --- .../ExecuteVStableSwapInvalidDiffTest.scala | 74 ++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala index b43ed71cc..da648dff2 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala @@ -33,38 +33,46 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec property("unable to withdraw tokens") { forAll(preconditionsAndVStableSwapDepositToken) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, depositBase: EC, withdrawBase: EC, withdrawBaseInvalid: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBase.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), TestBlock.createWithTxStatus(withdrawBase.timestamp, Seq(withdrawBase), TransactionStatus.Success)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } // withdraw tokens more than depositing in vstable swap contract - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBase.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), TestBlock.createWithTxStatus(withdrawBaseInvalid.timestamp, Seq(withdrawBaseInvalid), TransactionStatus.ContractTokenBalanceInsufficient)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient } } } - val preconditionsAndVStableSwapSetOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + val preconditionsAndVStableSwapSetOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attachment) <- createBaseTokenTargetTokenAndInitVStableSwap(1000, 1, 1000, 1000, - 1, 1000, 5, 1, 1) - setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 1000, 1000, attachment, fee, ts+7) + 1, 1000, 2, 1, 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 100, 100, attachment, fee, ts+7) + setOrder2 <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 100, 100, attachment, fee, ts+8) + setOrder3 <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 100, 100, attachment, fee, ts+9) setOrderInvalid <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 10, 1000, 10, 1000, 10, 10, 10000, 1000, attachment, fee, ts+7) - } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, setOrderInvalid) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, setOrder2, setOrder3, setOrderInvalid) property("unable to set order") { forAll(preconditionsAndVStableSwapSetOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, - regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, setOrderInvalid: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget))), + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, setOrder2: EC, setOrder3: EC, setOrderInvalid: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositTarget.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget))), TestBlock.createWithTxStatus(setOrder.timestamp, Seq(setOrder), TransactionStatus.Success)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } - // deposit into contract is less than deposit into order - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget))), + // set order and deposit into contract which is less than deposit into order + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositTarget.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget))), TestBlock.createWithTxStatus(setOrderInvalid.timestamp, Seq(setOrderInvalid), TransactionStatus.ContractMapValueInsufficient)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } + // set order more than maxOrderPerUser + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder)), + TestBlock.create(setOrder2.timestamp, Seq(setOrder2))), + TestBlock.createWithTxStatus(setOrder3.timestamp, Seq(setOrder3), TransactionStatus.Failed)) { (blockDiffEi, _) => + blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed + } } } @@ -82,17 +90,17 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec property("unable to update order") { forAll(preconditionsAndVStableSwapUpdateOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, closeOrder: EC, updateOrder: EC, updateOrderInvalid: EC) => - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(updateOrder.timestamp, Seq(updateOrder), TransactionStatus.Success)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success } // update order with wrong order id - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(updateOrderInvalid.timestamp, Seq(updateOrderInvalid), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined } // update order after close order - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(closeOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), TestBlock.createWithTxStatus(updateOrder.timestamp, Seq(updateOrder), TransactionStatus.Failed)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } @@ -114,22 +122,22 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec forAll(preconditionsAndVStableSwapOrderDeposit) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, closeOrder: EC, orderDeposit: EC, orderDepositInvalid: EC, orderDepositInvalid2: EC) => - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderDeposit.timestamp, Seq(orderDeposit), TransactionStatus.Success)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success } // deposit into order is greater than deposit into contract - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderDepositInvalid.timestamp, Seq(orderDepositInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } // order deposit with wrong order id - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderDepositInvalid2.timestamp, Seq(orderDepositInvalid2), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined } // order deposit after order close - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(closeOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), TestBlock.createWithTxStatus(orderDeposit.timestamp, Seq(orderDeposit), TransactionStatus.Failed)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } @@ -151,23 +159,23 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec forAll(preconditionsAndVStableSwapOrderWithdraw) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, closeOrder: EC, orderWithdraw: EC, orderWithdrawInvalid: EC, orderWithdrawInvalid2: EC) => - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderWithdraw.timestamp, Seq(orderWithdraw), TransactionStatus.Success)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Success } // withdraw from contract is greater than deposit into order - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderWithdrawInvalid.timestamp, Seq(orderWithdrawInvalid), TransactionStatus.ContractMapValueInsufficient)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } // order withdraw with wrong order id - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderWithdrawInvalid2.timestamp, Seq(orderWithdrawInvalid2), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined } // order withdraw after order close - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(closeOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), TestBlock.createWithTxStatus(orderWithdraw.timestamp, Seq(orderWithdraw), TransactionStatus.Failed)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } @@ -186,12 +194,12 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec property("unable to close order") { forAll(preconditionsAndVStableSwapOrderClose) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, closeOrder: EC, closeOrderInvalid: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(closeOrder.timestamp, Seq(closeOrder), TransactionStatus.Success)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } // close order with wrong order id - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(closeOrderInvalid.timestamp, Seq(closeOrderInvalid), TransactionStatus.ContractStateMapNotDefined)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined } @@ -221,56 +229,56 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec forAll(preconditionsAndVStableSwapBaseToTarget) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, setOrder1: EC, setOrder2: EC, closeOrder: EC, swapBaseToTarget: EC, swapBaseToTargetInvalid: EC, swapBaseToTargetInvalid2: EC, swapBaseToTargetInvalid3: EC, swapBaseToTargetInvalid4: EC, swapBaseToTargetInvalid5: EC, swapBaseToTargetInvalid6: EC, swapBaseToTargetInvalid7: EC, swapBaseToTargetInvalid8: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(swapBaseToTarget.timestamp, Seq(swapBaseToTarget), TransactionStatus.Success)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success } // price is not equal to priceBase - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(swapBaseToTargetInvalid.timestamp, Seq(swapBaseToTargetInvalid), TransactionStatus.Failed)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed } // swapFee is not equal to baseFee - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(swapBaseToTargetInvalid2.timestamp, Seq(swapBaseToTargetInvalid2), TransactionStatus.Failed)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed } // swap base token with not enough depositing target token - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder1))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder1.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder1))), TestBlock.createWithTxStatus(swapBaseToTargetInvalid3.timestamp, Seq(swapBaseToTargetInvalid3), TransactionStatus.ContractMapValueInsufficient)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } // swap base token with not enough holding base token - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder2))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder2.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder2))), TestBlock.createWithTxStatus(swapBaseToTargetInvalid4.timestamp, Seq(swapBaseToTargetInvalid4), TransactionStatus.ContractMapValueInsufficient)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient } // swap base token with wrong deadline - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositTarget.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), TestBlock.create(setOrder.timestamp, Seq(setOrder))), TestBlock.createWithTxStatus(swapBaseToTargetInvalid5.timestamp, Seq(swapBaseToTargetInvalid5), TransactionStatus.Failed)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } // swap base token more than maxBase - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositTarget.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), TestBlock.create(setOrder.timestamp, Seq(setOrder))), TestBlock.createWithTxStatus(swapBaseToTargetInvalid6.timestamp, Seq(swapBaseToTargetInvalid6), TransactionStatus.Failed)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } // swap base token less than minBase - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositTarget.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), TestBlock.create(setOrder.timestamp, Seq(setOrder))), TestBlock.createWithTxStatus(swapBaseToTargetInvalid7.timestamp, Seq(swapBaseToTargetInvalid7), TransactionStatus.Failed)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.Failed } // swap base token with wrong order id - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositTarget.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget)), TestBlock.create(setOrder.timestamp, Seq(setOrder))), TestBlock.createWithTxStatus(swapBaseToTargetInvalid8.timestamp, Seq(swapBaseToTargetInvalid8), TransactionStatus.ContractStateMapNotDefined)) { (blockDiffEi, _) => blockDiffEi.txsDiff.txStatus shouldBe TransactionStatus.ContractStateMapNotDefined } // swap base token after order close - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(closeOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder, closeOrder))), TestBlock.createWithTxStatus(swapBaseToTarget.timestamp, Seq(swapBaseToTarget), TransactionStatus.Failed)) { blockDiffEi => blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed } From 3e5f928e4bce18154fd92dd630129f03fe660f7d Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 4 Feb 2021 18:01:10 +0800 Subject: [PATCH 244/391] Add VStableSwapOpcDiffTest and VStableSwapFunction --- .../vstableswap/VStableSwapFunction.scala | 41 ++++++++ .../vstableswap/VStableSwapOpcDiffTest.scala | 95 +++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunction.scala create mode 100644 src/test/scala/vsys/blockchain/state/contract/vstableswap/VStableSwapOpcDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunction.scala b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunction.scala new file mode 100644 index 000000000..f2e2ad085 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunction.scala @@ -0,0 +1,41 @@ +package vsys.blockchain.contract.vstableswap + +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.contract.DataType +import vsys.blockchain.contract.ContractVStableSwap._ + +trait VStableSwapFunction { + + val initId: Short = 0 + + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.TokenId.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) + + val initWrongDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) + + val initTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(5.toByte), + cdbvSet ++ Array(makerStateVar.index, 5.toByte), + cdbvSet ++ Array(baseTokenIdStateVar.index, 0.toByte), + cdbvSet ++ Array(targetTokenIdStateVar.index, 1.toByte), + cdbvSet ++ Array(maxOrderPerUserStateVar.index, 2.toByte), + cdbvSet ++ Array(unitPriceBaseStateVar.index, 3.toByte), + cdbvSet ++ Array(unitPriceTargetStateVar.index, 4.toByte) + ) + + val initWrongTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(5.toByte), + cdbvSet ++ Array(makerStateVar.index, 5.toByte), + cdbvSet ++ Array(baseTokenIdStateVar.index, 0.toByte), + cdbvSet ++ Array(targetTokenIdStateVar.index, 1.toByte), + cdbvSet ++ Array(maxOrderPerUserStateVar.index, 2.toByte), + cdbvSet ++ Array(unitPriceBaseStateVar.index, 3.toByte), + Array(5.toByte, 3.toByte) ++ Array(unitPriceTargetStateVar.index, 4.toByte) + ) + + val nonReturnType: Array[Byte] = Array[Byte]() + val onInitTriggerType: Byte = 0 + + lazy val wrongDataTrigger: Seq[Array[Byte]] = Seq(getFunctionBytes(initId, onInitTriggerType, nonReturnType, initWrongDataType, initTriggerOpcs)) + lazy val wrongOpcTrigger: Seq[Array[Byte]] = Seq(getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initWrongTriggerOpcs)) + +} diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/VStableSwapOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/VStableSwapOpcDiffTest.scala new file mode 100644 index 000000000..b45123b9c --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/VStableSwapOpcDiffTest.scala @@ -0,0 +1,95 @@ +package vsys.blockchain.state.contract.vstableswap + +import com.google.common.primitives.Ints +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.block.TestBlock +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.state.EitherExt2 +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.ValidationError.{ContractDataTypeMismatch, ContractInvalidOPCData} +import vsys.blockchain.contract._ +import vsys.blockchain.contract.vstableswap.{VStableSwapContractGen, VStableSwapFunction} +import vsys.blockchain.transaction.contract._ + +class VStableSwapOpcDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with VStableSwapContractGen + with VStableSwapFunction { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val regContract: Gen[Contract] = + Gen.const(Contract.buildContract(ContractVStableSwap.contract.languageCode, ContractVStableSwap.contract.languageVersion, + ContractVStableSwap.contract.trigger, ContractVStableSwap.contract.descriptor, ContractVStableSwap.contract.stateVar, + ContractVStableSwap.contract.stateMap, ContractVStableSwap.contract.textual).explicitGet()) + + val preconditionsAndRegContract: Gen[(GenesisTransaction, RegisterContractTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contract <- regContract + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + data <- initVStableSwapDataStackGen(tokenId.arr, tokenId.arr, 5, 1, 1) + description <- validDescStringGen + genesis <- genesisVStableSwapGen(master, ts) + create <- registerVStableSwapGen(master, contract, data, description, fee, ts + 1) + } yield (genesis, create) + + property("register contract transaction pass OpcFunDiff"){ + forAll(preconditionsAndRegContract) { case (genesis, create) => + assertOpcFuncDifferEi(2, None, create) { opcFunDiffEi => + opcFunDiffEi shouldBe an[Right[_, _]] + } + assertDiffEi(Seq(TestBlock.create(Seq(genesis))), TestBlock.createWithTxStatus(Seq(create), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + } + } + } + + val regWrongParaContract: Gen[Contract] = + Gen.const(Contract.buildContract(ContractVStableSwap.contract.languageCode, ContractVStableSwap.contract.languageVersion, + wrongDataTrigger, ContractVStableSwap.contract.descriptor, ContractVStableSwap.contract.stateVar, + ContractVStableSwap.contract.stateMap, ContractVStableSwap.contract.textual).explicitGet()) + val preconditionsAndRegContractWrongPara: Gen[RegisterContractTransaction] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contract <- regWrongParaContract + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + data <- initVStableSwapDataStackGen(tokenId.arr, tokenId.arr, 5, 1, 1) + description <- validDescStringGen + create <- registerVStableSwapGen(master, contract, data, description, fee, ts) + } yield create + + property("register contract transaction cannot pass due to wrong list of parameters"){ + forAll(preconditionsAndRegContractWrongPara) { case create => + assertOpcFuncDifferEi(2, None, create) { opcFunDiffEi => + opcFunDiffEi shouldBe Left(ContractDataTypeMismatch) + } + } + } + + val regWrongOpcFunContract: Gen[Contract] = + Gen.const(Contract.buildContract(ContractVStableSwap.contract.languageCode, ContractVStableSwap.contract.languageVersion, + wrongOpcTrigger, ContractVStableSwap.contract.descriptor, ContractVStableSwap.contract.stateVar, + ContractVStableSwap.contract.stateMap, ContractVStableSwap.contract.textual).explicitGet()) + val preconditionsAndRegContractWrongFun: Gen[RegisterContractTransaction] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contract <- regWrongOpcFunContract + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + data <- initVStableSwapDataStackGen(tokenId.arr, tokenId.arr, 5, 1, 1) + description <- validDescStringGen + create <- registerVStableSwapGen(master, contract, data, description, fee, ts) + } yield create + + property("register contract transaction cannot pass due to wrong opcode"){ + forAll(preconditionsAndRegContractWrongFun) { case create => + assertOpcFuncDifferEi(2, None, create) { opcFunDiffEi => + opcFunDiffEi shouldBe Left(ContractInvalidOPCData) + } + } + } +} From 0623823baa626e3de0917b4c5e805fcf345a6134 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Thu, 4 Feb 2021 18:15:25 +0800 Subject: [PATCH 245/391] Add RegisterVStableSwapDiffTest --- .../RegisterVStableSwapDiffTest.scala | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/vstableswap/RegisterVStableSwapDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/RegisterVStableSwapDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/RegisterVStableSwapDiffTest.scala new file mode 100644 index 000000000..d212a7d46 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/RegisterVStableSwapDiffTest.scala @@ -0,0 +1,59 @@ +package vsys.blockchain.state.contract.vstableswap + +import cats.Monoid +import com.google.common.primitives.{Bytes, Ints} +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.vstableswap.VStableSwapContractGen +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen} +import vsys.blockchain.contract._ +import vsys.blockchain.state._ +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.contract.RegisterContractTransaction + +class RegisterVStableSwapDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with VStableSwapContractGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val stableSwapContract: Gen[Contract] = vStableSwapContractGen() + + val preconditionsAndStableSwapContractTest: Gen[(GenesisTransaction, RegisterContractTransaction, Long)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contract <- stableSwapContract + description <- validDescStringGen + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + dataStack <- initVStableSwapDataStackGen(tokenId.arr, tokenId.arr, 5, 1, 1) + regContract <- registerVStableSwapGen(master, contract, dataStack, description, fee + 10000000000L, ts) + genesis <- genesisVStableSwapGen(master, ts) + } yield (genesis, regContract, fee + 10000000000L) + + property("register stable swap contract function transactions doesn't break invariant") { + forAll(preconditionsAndStableSwapContractTest) { case (genesis, reg: RegisterContractTransaction, fee: Long) => + assertDiffAndState(Seq(TestBlock.create(Seq(genesis))), TestBlock.create(Seq(reg))) { (blockDiff, newState) => + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -fee + totalPortfolioDiff.effectiveBalance shouldBe -fee + val master = reg.proofs.firstCurveProof.explicitGet().publicKey + val contractId = reg.contractId.bytes + val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) + val tokenIdKey = ByteStr(Bytes.concat(contractId.arr, Array(1.toByte))) + val tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + val (_, masterTxs) = newState.accountTransactionIds(master, 2, 0) + masterTxs.size shouldBe 2 // genesis, reg + newState.contractContent(contractId) shouldEqual Some((2, reg.id, ContractVStableSwap.contract)) + newState.contractInfo(makerKey) shouldEqual Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(tokenIdKey) shouldEqual Some(DataEntry(tokenId.arr, DataType.TokenId)) + } + } + } +} From 818d9fa65cd6486e1f52a384c090631113bc4605 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Fri, 5 Feb 2021 11:05:14 +0800 Subject: [PATCH 246/391] handle leading bytes in convertion going from longer to shorter data types --- .../vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index cb8209154..8785b8102 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -90,8 +90,13 @@ object BasicOpcDiff extends OpcDiffer { } case _ => Left(ContractInvalidOPCData) } + def addLeadingZeros(in: Array[Byte], length: Int): Array[Byte] = - (new Array[Byte](0.max(length - in.length)) ++ in).takeRight(length) + if (in.length - length > 0) { + in.take(in.length - length).dropWhile(i => i == 0) ++ in.takeRight(length) + } else { + (new Array[Byte](0.max(length - in.length)) ++ in).takeRight(length) + } def concat(x: DataEntry, y: DataEntry): Either[ValidationError, DataEntry] = DataEntry.create(x.data ++ y.data, DataType.ShortBytes) @@ -140,5 +145,4 @@ object BasicOpcDiff extends OpcDiffer { private def checkBytesLength(bytes: Array[Byte], t: BasicType.BasicTypeVal): Boolean = { (t == BasicType.ConstantGet && bytes.length > t.len) || (bytes.length == t.len) } - } From 18b05da867051ba26850833a9d81e840aff09b57 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 2 Feb 2021 16:53:37 +0800 Subject: [PATCH 247/391] Add tests for update, deposit, withdraw and close orders --- .../ExecuteVStableSwapValidDiffTest.scala | 119 +++++++++++++++++- 1 file changed, 116 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala index 65afe2ef9..bc9ea3389 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala @@ -1,9 +1,11 @@ package vsys.blockchain.state.contract.vstableswap +import com.google.common.primitives.Bytes import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.token.SystemContractGen import vsys.blockchain.contract.vstableswap.{VStableSwapContractGen, VStableSwapFunctionHelperGen} import vsys.blockchain.state._ @@ -81,7 +83,7 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec } val preconditionsAndVStableSwapSupersedeAndSetOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { - (genesis, genesis2, master, user, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + (genesis, _, master, user, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) <- createBaseTokenTargetTokenAndInitVStableSwap( 1000, 1, @@ -94,7 +96,7 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec 1) supersede <- supersedeVStableSwapGen(master, regVStableSwapContract.contractId, user.toAddress, attach, fee, ts + 5) setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 1000, 1000, attach, fee, ts + 6) - } yield(genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, supersede, setOrder) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, supersede, setOrder) property("V Stable Swap able to supersede and set order") { forAll(preconditionsAndVStableSwapSupersedeAndSetOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, @@ -105,4 +107,115 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec } } } -} + + val preconditionsAndVStableSwapSetAndUpdateOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 1000, 1000, attach, fee, ts + 5) + updateOrder <- updateVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10, 10, 10, 100, 10, 100, 5, 5, attach, fee, ts + 6) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, updateOrder) + + property("V Stable Swap able to set and update orders") { + forAll(preconditionsAndVStableSwapSetAndUpdateOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, updateOrder: EC) => + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(updateOrder.timestamp, Seq(updateOrder), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regVStableSwap.contractId.bytes + + val orderId = DataEntry.create(setOrder.id.arr, DataType.ShortBytes).right.get.bytes + val orderOwnerKey = ByteStr(Bytes.concat(contractId.arr, Array(3.toByte), orderId)) + + newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(regVStableSwap.proofs.firstCurveProof.explicitGet().publicKey.toAddress.bytes.arr, DataType.Address)) + } + } + } + + val preconditionsAndVStableSwapSetAndOrderDeposit: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) + orderDeposit <- orderDepositVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 500, 500, attach, fee, ts + 6) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, orderDeposit) + + property("V Stable Swap able to set and deposit to orders") { + forAll(preconditionsAndVStableSwapSetAndOrderDeposit) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, orderDeposit: EC) => + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderDeposit.timestamp, Seq(orderDeposit), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVStableSwapSetAndOrderWithdraw: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) + orderWithdraw <- orderWithdrawVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 500, 500, attach, fee, ts + 6) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, orderWithdraw) + + property("V Stable Swap able to set and withdraw from orders") { + forAll(preconditionsAndVStableSwapSetAndOrderWithdraw) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, orderWithdraw: EC) => + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderWithdraw.timestamp, Seq(orderWithdraw), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVStableSwapSetAndOrderClose: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) + orderClose <- closeVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, attach, fee, ts + 6) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, orderClose) + + property("V Stable Swap able to close orders") { + forAll(preconditionsAndVStableSwapSetAndOrderClose) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, orderClose: EC) => + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(orderClose.timestamp, Seq(orderClose), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } +} \ No newline at end of file From 655c6e9128ee8c214bcbab116383f48bc4468274 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Wed, 3 Feb 2021 10:52:19 +0800 Subject: [PATCH 248/391] Add tests for Swap in Stable Swap Contract --- .../ExecuteVStableSwapValidDiffTest.scala | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala index bc9ea3389..4d22b8874 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala @@ -218,4 +218,56 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec } } } + + val preconditionsAndVStableSwapSetAndSwapBaseToTarget: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) + swapBaseToTarget <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 100, 0, 1, ts + 10, attach, fee, ts + 6) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, swapBaseToTarget) + + property("V Stable Swap able to swap base to target") { + forAll(preconditionsAndVStableSwapSetAndSwapBaseToTarget) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, swapBaseToTarget: EC) => + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(swapBaseToTarget.timestamp, Seq(swapBaseToTarget), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsAndVStableSwapSetAndSwapTargetToBase: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { + (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + <- createBaseTokenTargetTokenAndInitVStableSwap( + 1000, + 1, + 1000, + 1000, + 1, + 1000, + 5, + 1, + 1) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) + swapTargetToBase <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 100, 0, 1, ts + 10, attach, fee, ts + 6) + } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, swapTargetToBase) + + property("V Stable Swap able to swap target to base") { + forAll(preconditionsAndVStableSwapSetAndSwapTargetToBase) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, + regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, setOrder: EC, swapTargetToBase: EC) => + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), + TestBlock.createWithTxStatus(swapTargetToBase.timestamp, Seq(swapTargetToBase), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } } \ No newline at end of file From 56b38b8265c60794010807915b4db2449349808b Mon Sep 17 00:00:00 2001 From: twwu123 Date: Fri, 5 Feb 2021 18:19:12 +0800 Subject: [PATCH 249/391] Add helper functions to generate contract db keys --- .../VStableSwapFunctionHelperGen.scala | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunctionHelperGen.scala index ddbd20772..f71e467e9 100644 --- a/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunctionHelperGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vstableswap/VStableSwapFunctionHelperGen.scala @@ -1,12 +1,13 @@ package vsys.blockchain.contract.vstableswap -import com.google.common.primitives.{Ints, Longs} +import com.google.common.primitives.{Bytes, Ints, Longs} import org.scalacheck.Gen import vsys.account.ContractAccount.tokenIdFromBytes -import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.account.{Address, ContractAccount, PrivateKeyAccount, PublicKeyAccount} import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.token.TokenContractGen import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.state.ByteStr import vsys.blockchain.transaction.GenesisTransaction import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} @@ -104,4 +105,57 @@ trait VStableSwapFunctionHelperGen extends VStableSwapContractGen with TokenCont depositBase <- depositToken(master, tokenBaseContractId, master.toAddress.bytes.arr, regVStableSwapContract.contractId.bytes.arr, issueAmountBase, fee, ts + 5) depositTarget <- depositToken(master, tokenTargetContractId, master.toAddress.bytes.arr, regVStableSwapContract.contractId.bytes.arr, issueAmountTarget, fee, ts + 6) } yield (genesis, genesis2, master, user, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) + + def getContractTokenBalanceKeys(tokenBaseContractId: Array[Byte], tokenTargetContractId: Array[Byte], vStableSwapContractId: Array[Byte]): (ByteStr, ByteStr) = { + val tokenBaseId = tokenIdFromBytes(tokenBaseContractId, Ints.toByteArray(0)).explicitGet() + val tokenTargetId = tokenIdFromBytes(tokenTargetContractId, Ints.toByteArray(0)).explicitGet() + + val contractTokenBaseBalanceKey = ByteStr(Bytes.concat(tokenBaseId.arr, vStableSwapContractId)) + val contractTokenTargetBalanceKey = ByteStr(Bytes.concat(tokenTargetId.arr, vStableSwapContractId)) + + (contractTokenBaseBalanceKey, contractTokenTargetBalanceKey) + } + + def getUserTokenBalanceKeys(tokenBaseContractId: Array[Byte], tokenTargetContractId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr) = { + val tokenBaseId = tokenIdFromBytes(tokenBaseContractId, Ints.toByteArray(0)).explicitGet() + val tokenTargetId = tokenIdFromBytes(tokenTargetContractId, Ints.toByteArray(0)).explicitGet() + + val userTokenBaseBalanceKey = ByteStr(Bytes.concat(tokenBaseId.arr, user.toAddress.bytes.arr)) + val userTokenTargetBalanceKey = ByteStr(Bytes.concat(tokenTargetId.arr, user.toAddress.bytes.arr)) + + (userTokenBaseBalanceKey, userTokenTargetBalanceKey) + } + + def getStableSwapContractStateVarKeys(vStableSwapContractId: Array[Byte]): (ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr) = { + val makerKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(0.toByte))) + val baseTokenIdKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(1.toByte))) + val targetTokenIdKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(2.toByte))) + val maxOrderPerUserKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(3.toByte))) + val unitPriceBaseKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(4.toByte))) + val unitPriceTargetKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(5.toByte))) + + (makerKey, baseTokenIdKey, targetTokenIdKey, maxOrderPerUserKey, unitPriceBaseKey, unitPriceTargetKey) + } + + def getStableSwapContractStateMapKeys(vStableSwapContractId: Array[Byte], orderId: Array[Byte], user: PublicKeyAccount): (ByteStr, ByteStr, ByteStr, + ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr, ByteStr) = { + val baseTokenBalanceKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(0.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val targetTokenBalanceKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(1.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val userOrdersKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(2.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + val orderOwnerKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(3.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val feeBaseKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(4.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val feeTargetKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(5.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val minBaseKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(6.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val maxBaseKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(7.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val minTargetKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(8.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val maxTargetKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(9.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val priceBaseKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(10.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val priceTargetKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(11.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val baseTokenLockedKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(12.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val targetTokenLockedKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(13.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderStatusKey = ByteStr(Bytes.concat(vStableSwapContractId, Array(14.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + + (baseTokenBalanceKey, targetTokenBalanceKey, userOrdersKey, orderOwnerKey, feeBaseKey, feeTargetKey, minBaseKey, maxBaseKey, + minTargetKey, maxTargetKey, priceBaseKey, priceTargetKey, baseTokenLockedKey, targetTokenLockedKey, orderStatusKey) + } } From 2c8a1be87614cf84bd1fe307d3418c12bd1809f9 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Fri, 5 Feb 2021 18:25:29 +0800 Subject: [PATCH 250/391] Add tests for DB values in each unit test --- .../ExecuteVStableSwapValidDiffTest.scala | 474 +++++++++++++----- 1 file changed, 361 insertions(+), 113 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala index 4d22b8874..bd0b288c4 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapValidDiffTest.scala @@ -1,15 +1,16 @@ package vsys.blockchain.state.contract.vstableswap -import com.google.common.primitives.Bytes +import com.google.common.primitives.{Longs, Ints} +import vsys.account.ContractAccount.tokenIdFromBytes import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.block.TestBlock -import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.contract.token.SystemContractGen import vsys.blockchain.contract.vstableswap.{VStableSwapContractGen, VStableSwapFunctionHelperGen} -import vsys.blockchain.state._ import vsys.blockchain.state.diffs._ +import vsys.blockchain.state._ +import vsys.blockchain.contract.{DataEntry, DataType} import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction => EC, RegisterContractTransaction => RC} import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} @@ -27,27 +28,49 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapDepositToken: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC)] = for { (genesis, _, _, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, _, _, _) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unitPriceBase + 1) // unitPriceTarget } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget) property("V Stable Swap able to deposit") { forAll(preconditionsAndVStableSwapDepositToken) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase))), - TestBlock.createWithTxStatus(depositBase.timestamp, Seq(depositBase), TransactionStatus.Success)) { blockDiffEi => - blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase))), + TestBlock.createWithTxStatus(depositBase.timestamp, Seq(depositBase), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val (contractTokenBaseBalanceKey, _) = getContractTokenBalanceKeys(regBase.contractId.bytes.arr, regTarget.contractId.bytes.arr, + regVStableSwap.contractId.bytes.arr) + + newState.tokenAccountBalance(contractTokenBaseBalanceKey) shouldEqual 1000L + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (masterTokenBaseBalanceKey, _) = getUserTokenBalanceKeys(regBase.contractId.bytes.arr, regTarget.contractId.bytes.arr, master) + + newState.tokenAccountBalance(masterTokenBaseBalanceKey) shouldEqual 0L } - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueTarget))), - TestBlock.createWithTxStatus(depositBase.timestamp, Seq(depositTarget), TransactionStatus.Success)) { blockDiffEi => - blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueTarget))), + TestBlock.createWithTxStatus(depositBase.timestamp, Seq(depositTarget), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val (_, contractTokenTargetBalanceKey) = getContractTokenBalanceKeys(regBase.contractId.bytes.arr, regTarget.contractId.bytes.arr, + regVStableSwap.contractId.bytes.arr) + + newState.tokenAccountBalance(contractTokenTargetBalanceKey) shouldEqual 1000L + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (_, masterTokenTargetBalanceKey) = getUserTokenBalanceKeys(regBase.contractId.bytes.arr, regTarget.contractId.bytes.arr, master) + + newState.tokenAccountBalance(masterTokenTargetBalanceKey) shouldEqual 0L } } } @@ -55,29 +78,51 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapWithdrawToken: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, _) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) - withdrawBase <- withdrawToken(master, regTokenBase.contractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 1000, fee, ts + 7) - withdrawTarget <- withdrawToken(master, regTokenTarget.contractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 1000, fee, ts + 8) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unitPriceBase + 1) // unitPriceTarget + withdrawBase <- withdrawToken(master, regTokenBase.contractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 500L, fee, ts + 7) + withdrawTarget <- withdrawToken(master, regTokenTarget.contractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 500L, fee, ts + 8) } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, withdrawBase, withdrawTarget) property("V Stable Swap able to withdraw") { forAll(preconditionsAndVStableSwapWithdrawToken) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, withdrawBase: EC, withdrawTarget: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBase.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), - TestBlock.createWithTxStatus(withdrawBase.timestamp, Seq(withdrawBase), TransactionStatus.Success)) { blockDiffEi => - blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBase.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, depositBase))), + TestBlock.createWithTxStatus(withdrawBase.timestamp, Seq(withdrawBase), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val (contractTokenBaseBalanceKey, _) = getContractTokenBalanceKeys(regBase.contractId.bytes.arr, regTarget.contractId.bytes.arr, + regVStableSwap.contractId.bytes.arr) + + newState.tokenAccountBalance(contractTokenBaseBalanceKey) shouldEqual 500L + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (masterTokenBaseBalanceKey, _) = getUserTokenBalanceKeys(regBase.contractId.bytes.arr, regTarget.contractId.bytes.arr, master) + + newState.tokenAccountBalance(masterTokenBaseBalanceKey) shouldEqual 500L } - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueTarget, depositTarget))), - TestBlock.createWithTxStatus(withdrawTarget.timestamp, Seq(withdrawTarget), TransactionStatus.Success)) { blockDiffEi => - blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(regVStableSwap.timestamp, Seq(regBase, regTarget, regVStableSwap, issueTarget, depositTarget))), + TestBlock.createWithTxStatus(withdrawTarget.timestamp, Seq(withdrawTarget), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val (_, contractTokenTargetBalanceKey) = getContractTokenBalanceKeys(regBase.contractId.bytes.arr, regTarget.contractId.bytes.arr, + regVStableSwap.contractId.bytes.arr) + + newState.tokenAccountBalance(contractTokenTargetBalanceKey) shouldEqual 500L + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (_, masterTokenTargetBalanceKey) = getUserTokenBalanceKeys(regBase.contractId.bytes.arr, regTarget.contractId.bytes.arr, master) + + newState.tokenAccountBalance(masterTokenTargetBalanceKey) shouldEqual 500L } } } @@ -85,25 +130,54 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapSupersedeAndSetOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, user, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unitPriceBase + 1) // unitPriceTarget supersede <- supersedeVStableSwapGen(master, regVStableSwapContract.contractId, user.toAddress, attach, fee, ts + 5) - setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 1000, 1000, attach, fee, ts + 6) + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 1, 1, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 6) } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, supersede, setOrder) property("V Stable Swap able to supersede and set order") { forAll(preconditionsAndVStableSwapSupersedeAndSetOrder) { case (genesis: GenesisTransaction, regBase: RC, regTarget: RC, regVStableSwap: RC, issueBase: EC, issueTarget: EC, depositBase: EC, depositTarget: EC, supersede: EC, setOrder: EC) => - assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBase.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, supersede))), - TestBlock.createWithTxStatus(setOrder.timestamp, Seq(setOrder), TransactionStatus.Success)) { blockDiffEi => - blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(depositBase.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, supersede))), + TestBlock.createWithTxStatus(setOrder.timestamp, Seq(setOrder), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (_, baseTokenIdKey, targetTokenIdKey, maxOrderPerUserKey, unitPriceBaseKey, unitPriceTargetKey) = getStableSwapContractStateVarKeys(regVStableSwap.contractId.bytes.arr) + + newState.contractInfo(baseTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regBase.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(targetTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regTarget.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(maxOrderPerUserKey) shouldBe Some(DataEntry(Longs.toByteArray(5), DataType.Amount)) + newState.contractInfo(unitPriceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + newState.contractInfo(unitPriceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + + val (baseTokenBalanceKey, targetTokenBalanceKey, userOrdersKey, orderOwnerKey, feeBaseKey, feeTargetKey, minBaseKey, maxBaseKey, + minTargetKey, maxTargetKey, priceBaseKey, priceTargetKey, baseTokenLockedKey, targetTokenLockedKey, orderStatusKey) = getStableSwapContractStateMapKeys(regVStableSwap.contractId.bytes.arr, setOrder.id.arr, master) + + newState.contractNumInfo(baseTokenBalanceKey) shouldBe 500L + newState.contractNumInfo(targetTokenBalanceKey) shouldBe 500L + newState.contractNumInfo(userOrdersKey) shouldBe 1L + newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(feeBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(feeTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(minBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(minTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(priceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(priceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(baseTokenLockedKey) shouldBe 500L + newState.contractNumInfo(targetTokenLockedKey) shouldBe 500L + newState.contractInfo(orderStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) } } } @@ -111,16 +185,16 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapSetAndUpdateOrder: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) - setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 1000, 1000, attach, fee, ts + 5) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unitPriceBase + 1) // unitPriceTarget + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) updateOrder <- updateVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 10, 10, 10, 100, 10, 100, 5, 5, attach, fee, ts + 6) } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, updateOrder) @@ -131,12 +205,35 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec TestBlock.createWithTxStatus(updateOrder.timestamp, Seq(updateOrder), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success - val contractId = regVStableSwap.contractId.bytes + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (makerKey, baseTokenIdKey, targetTokenIdKey, maxOrderPerUserKey, unitPriceBaseKey, unitPriceTargetKey) = getStableSwapContractStateVarKeys(regVStableSwap.contractId.bytes.arr) - val orderId = DataEntry.create(setOrder.id.arr, DataType.ShortBytes).right.get.bytes - val orderOwnerKey = ByteStr(Bytes.concat(contractId.arr, Array(3.toByte), orderId)) + newState.contractInfo(makerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(baseTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regBase.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(targetTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regTarget.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(maxOrderPerUserKey) shouldBe Some(DataEntry(Longs.toByteArray(5), DataType.Amount)) + newState.contractInfo(unitPriceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + newState.contractInfo(unitPriceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) - newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(regVStableSwap.proofs.firstCurveProof.explicitGet().publicKey.toAddress.bytes.arr, DataType.Address)) + val (baseTokenBalanceKey, targetTokenBalanceKey, userOrdersKey, orderOwnerKey, feeBaseKey, feeTargetKey, minBaseKey, maxBaseKey, + minTargetKey, maxTargetKey, priceBaseKey, priceTargetKey, baseTokenLockedKey, targetTokenLockedKey, orderStatusKey) = getStableSwapContractStateMapKeys(regVStableSwap.contractId.bytes.arr, setOrder.id.arr, master) + + newState.contractNumInfo(baseTokenBalanceKey) shouldBe 500L + newState.contractNumInfo(targetTokenBalanceKey) shouldBe 500L + newState.contractNumInfo(userOrdersKey) shouldBe 1L + newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(feeBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(feeTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(minBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(maxBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(minTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(10L), DataType.Amount)) + newState.contractInfo(maxTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(priceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(5L), DataType.Amount)) + newState.contractInfo(priceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(5L), DataType.Amount)) + newState.contractNumInfo(baseTokenLockedKey) shouldBe 500L + newState.contractNumInfo(targetTokenLockedKey) shouldBe 500L + newState.contractInfo(orderStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) } } } @@ -144,17 +241,17 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapSetAndOrderDeposit: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) - setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) - orderDeposit <- orderDepositVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 500, 500, attach, fee, ts + 6) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unitPriceBase + 1) // unitPriceTarget + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 5, 5, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) + orderDeposit <- orderDepositVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 100, 100, attach, fee, ts + 6) } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, orderDeposit) property("V Stable Swap able to set and deposit to orders") { @@ -163,6 +260,36 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderDeposit.timestamp, Seq(orderDeposit), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (makerKey, baseTokenIdKey, targetTokenIdKey, maxOrderPerUserKey, unitPriceBaseKey, unitPriceTargetKey) = getStableSwapContractStateVarKeys(regVStableSwap.contractId.bytes.arr) + + newState.contractInfo(makerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(baseTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regBase.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(targetTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regTarget.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(maxOrderPerUserKey) shouldBe Some(DataEntry(Longs.toByteArray(5), DataType.Amount)) + newState.contractInfo(unitPriceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + newState.contractInfo(unitPriceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + + val (baseTokenBalanceKey, targetTokenBalanceKey, userOrdersKey, orderOwnerKey, feeBaseKey, feeTargetKey, minBaseKey, maxBaseKey, + minTargetKey, maxTargetKey, priceBaseKey, priceTargetKey, baseTokenLockedKey, targetTokenLockedKey, orderStatusKey) = getStableSwapContractStateMapKeys(regVStableSwap.contractId.bytes.arr, setOrder.id.arr, master) + + newState.contractNumInfo(baseTokenBalanceKey) shouldBe 400L + newState.contractNumInfo(targetTokenBalanceKey) shouldBe 400L + newState.contractNumInfo(userOrdersKey) shouldBe 1L + newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(feeBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(5L), DataType.Amount)) + newState.contractInfo(feeTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(5L), DataType.Amount)) + newState.contractInfo(minBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(minTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(priceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(priceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(baseTokenLockedKey) shouldBe 600L + newState.contractNumInfo(targetTokenLockedKey) shouldBe 600L + newState.contractInfo(orderStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) } } } @@ -170,17 +297,17 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapSetAndOrderWithdraw: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) - setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) - orderWithdraw <- orderWithdrawVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 500, 500, attach, fee, ts + 6) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unitPriceBase + 1) // unitPriceTarget + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 5, 5, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) + orderWithdraw <- orderWithdrawVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 100, 100, attach, fee, ts + 6) } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, orderWithdraw) property("V Stable Swap able to set and withdraw from orders") { @@ -189,6 +316,36 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderWithdraw.timestamp, Seq(orderWithdraw), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (makerKey, baseTokenIdKey, targetTokenIdKey, maxOrderPerUserKey, unitPriceBaseKey, unitPriceTargetKey) = getStableSwapContractStateVarKeys(regVStableSwap.contractId.bytes.arr) + + newState.contractInfo(makerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(baseTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regBase.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(targetTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regTarget.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(maxOrderPerUserKey) shouldBe Some(DataEntry(Longs.toByteArray(5), DataType.Amount)) + newState.contractInfo(unitPriceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + newState.contractInfo(unitPriceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + + val (baseTokenBalanceKey, targetTokenBalanceKey, userOrdersKey, orderOwnerKey, feeBaseKey, feeTargetKey, minBaseKey, maxBaseKey, + minTargetKey, maxTargetKey, priceBaseKey, priceTargetKey, baseTokenLockedKey, targetTokenLockedKey, orderStatusKey) = getStableSwapContractStateMapKeys(regVStableSwap.contractId.bytes.arr, setOrder.id.arr, master) + + newState.contractNumInfo(baseTokenBalanceKey) shouldBe 600L + newState.contractNumInfo(targetTokenBalanceKey) shouldBe 600L + newState.contractNumInfo(userOrdersKey) shouldBe 1L + newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(feeBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(5L), DataType.Amount)) + newState.contractInfo(feeTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(5L), DataType.Amount)) + newState.contractInfo(minBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(minTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(priceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(priceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(baseTokenLockedKey) shouldBe 400L + newState.contractNumInfo(targetTokenLockedKey) shouldBe 400L + newState.contractInfo(orderStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) } } } @@ -196,16 +353,16 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapSetAndOrderClose: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) - setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unitPriceBase + 1) // unitPriceTarget + setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 1, 1, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) orderClose <- closeVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, attach, fee, ts + 6) } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, orderClose) @@ -215,6 +372,37 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(orderClose.timestamp, Seq(orderClose), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (makerKey, baseTokenIdKey, targetTokenIdKey, maxOrderPerUserKey, unitPriceBaseKey, unitPriceTargetKey) = getStableSwapContractStateVarKeys(regVStableSwap.contractId.bytes.arr) + + newState.contractInfo(makerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + + newState.contractInfo(baseTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regBase.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(targetTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regTarget.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(maxOrderPerUserKey) shouldBe Some(DataEntry(Longs.toByteArray(5), DataType.Amount)) + newState.contractInfo(unitPriceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + newState.contractInfo(unitPriceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + + val (baseTokenBalanceKey, targetTokenBalanceKey, userOrdersKey, orderOwnerKey, feeBaseKey, feeTargetKey, minBaseKey, maxBaseKey, + minTargetKey, maxTargetKey, priceBaseKey, priceTargetKey, baseTokenLockedKey, targetTokenLockedKey, orderStatusKey) = getStableSwapContractStateMapKeys(regVStableSwap.contractId.bytes.arr, setOrder.id.arr, master) + + newState.contractNumInfo(baseTokenBalanceKey) shouldBe 1000L + newState.contractNumInfo(targetTokenBalanceKey) shouldBe 1000L + newState.contractNumInfo(userOrdersKey) shouldBe 0L + newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(feeBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(feeTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(minBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(minTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(priceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(priceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(baseTokenLockedKey) shouldBe 0L + newState.contractNumInfo(targetTokenLockedKey) shouldBe 0L + newState.contractInfo(orderStatusKey) shouldBe Some(DataEntry(Array(0.toByte), DataType.Boolean)) } } } @@ -222,15 +410,15 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapSetAndSwapBaseToTarget: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unitPriceBase + 1) // unitPriceTarget setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) swapBaseToTarget <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 100, 0, 1, ts + 10, attach, fee, ts + 6) } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, swapBaseToTarget) @@ -241,6 +429,36 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(swapBaseToTarget.timestamp, Seq(swapBaseToTarget), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (makerKey, baseTokenIdKey, targetTokenIdKey, maxOrderPerUserKey, unitPriceBaseKey, unitPriceTargetKey) = getStableSwapContractStateVarKeys(regVStableSwap.contractId.bytes.arr) + + newState.contractInfo(makerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(baseTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regBase.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(targetTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regTarget.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(maxOrderPerUserKey) shouldBe Some(DataEntry(Longs.toByteArray(5), DataType.Amount)) + newState.contractInfo(unitPriceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + newState.contractInfo(unitPriceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + + val (baseTokenBalanceKey, targetTokenBalanceKey, userOrdersKey, orderOwnerKey, feeBaseKey, feeTargetKey, minBaseKey, maxBaseKey, + minTargetKey, maxTargetKey, priceBaseKey, priceTargetKey, baseTokenLockedKey, targetTokenLockedKey, orderStatusKey) = getStableSwapContractStateMapKeys(regVStableSwap.contractId.bytes.arr, setOrder.id.arr, master) + + newState.contractNumInfo(baseTokenBalanceKey) shouldBe 400L + newState.contractNumInfo(targetTokenBalanceKey) shouldBe 600L + newState.contractNumInfo(userOrdersKey) shouldBe 1L + newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(feeBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(feeTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(minBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(minTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(priceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(priceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(baseTokenLockedKey) shouldBe 600L + newState.contractNumInfo(targetTokenLockedKey) shouldBe 400L + newState.contractInfo(orderStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) } } } @@ -248,17 +466,17 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec val preconditionsAndVStableSwapSetAndSwapTargetToBase: Gen[(GenesisTransaction, RC, RC, RC, EC, EC, EC, EC, EC, EC)] = for { (genesis, _, master, _, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, fee, ts, attach) <- createBaseTokenTargetTokenAndInitVStableSwap( - 1000, - 1, - 1000, - 1000, - 1, - 1000, - 5, - 1, - 1) + 1000, // totalSupplyBase + 1, // unityBase + 1000, // issueAmountBase + 1000, // totalSupplyTarget + 1, // unityTarget + 1000, // issueAmountTarget + 5, // maxOrderPerUser + 1, // unityPriceBase + 1) // unitPriceTarget setOrder <- setOrderVStableSwapGen(master, regVStableSwapContract.contractId, 0, 0, 0, 100, 0, 100, 1, 1, 500, 500, attach, fee, ts + 5) - swapTargetToBase <- swapBaseToTargetVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 100, 0, 1, ts + 10, attach, fee, ts + 6) + swapTargetToBase <- swapTargetToBaseVStableSwapGen(master, regVStableSwapContract.contractId, setOrder.id.arr, 100, 0, 1, ts + 10, attach, fee, ts + 6) } yield (genesis, regTokenBase, regTokenTarget, regVStableSwapContract, issueTokenBase, issueTokenTarget, depositBase, depositTarget, setOrder, swapTargetToBase) property("V Stable Swap able to swap target to base") { @@ -267,6 +485,36 @@ class ExecuteVStableSwapValidDiffTest extends PropSpec assertDiffAndState(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(setOrder.timestamp, Seq(regBase, regTarget, regVStableSwap, issueBase, issueTarget, depositBase, depositTarget, setOrder))), TestBlock.createWithTxStatus(swapTargetToBase.timestamp, Seq(swapTargetToBase), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val master = regBase.proofs.firstCurveProof.explicitGet().publicKey + + val (makerKey, baseTokenIdKey, targetTokenIdKey, maxOrderPerUserKey, unitPriceBaseKey, unitPriceTargetKey) = getStableSwapContractStateVarKeys(regVStableSwap.contractId.bytes.arr) + + newState.contractInfo(makerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(baseTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regBase.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(targetTokenIdKey) shouldBe Some(DataEntry(tokenIdFromBytes(regTarget.contractId.bytes.arr, Ints.toByteArray(0)).right.get.arr, DataType.TokenId)) + newState.contractInfo(maxOrderPerUserKey) shouldBe Some(DataEntry(Longs.toByteArray(5), DataType.Amount)) + newState.contractInfo(unitPriceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + newState.contractInfo(unitPriceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1), DataType.Amount)) + + val (baseTokenBalanceKey, targetTokenBalanceKey, userOrdersKey, orderOwnerKey, feeBaseKey, feeTargetKey, minBaseKey, maxBaseKey, + minTargetKey, maxTargetKey, priceBaseKey, priceTargetKey, baseTokenLockedKey, targetTokenLockedKey, orderStatusKey) = getStableSwapContractStateMapKeys(regVStableSwap.contractId.bytes.arr, setOrder.id.arr, master) + + newState.contractNumInfo(baseTokenBalanceKey) shouldBe 600L + newState.contractNumInfo(targetTokenBalanceKey) shouldBe 400L + newState.contractNumInfo(userOrdersKey) shouldBe 1L + newState.contractInfo(orderOwnerKey) shouldBe Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(feeBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(feeTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(minBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(minTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(0L), DataType.Amount)) + newState.contractInfo(maxTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.contractInfo(priceBaseKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractInfo(priceTargetKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) + newState.contractNumInfo(baseTokenLockedKey) shouldBe 400L + newState.contractNumInfo(targetTokenLockedKey) shouldBe 600L + newState.contractInfo(orderStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) } } } From 6959284007fc6a2d4fa2c470fe99475877846cfc Mon Sep 17 00:00:00 2001 From: twwu123 Date: Mon, 8 Feb 2021 10:59:54 +0800 Subject: [PATCH 251/391] add unit tests for very long BigInt to other data types --- .../state/opcdiffs/ConvertOpcDiffTest.scala | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala index b1913b843..95aae9747 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala @@ -111,7 +111,7 @@ class ConvertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriv ) } property("test overflow to Int32") { - BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Int.MaxValue + 1).toByteArray.length.toShort) ++ BigInt(Int.MaxValue + 1).toByteArray, DataType.BigInteger), Int32DataTypeObj) should be ( + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray((BigInt(Int.MaxValue) + 1).toByteArray.length.toShort) ++ (BigInt(Int.MaxValue) + 1).toByteArray, DataType.BigInteger), Int32DataTypeObj) should be ( Left(ValidationError.OverflowError) ) BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Int.MaxValue + 1), DataType.Amount), Int32DataTypeObj) should be ( @@ -120,28 +120,36 @@ class ConvertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriv BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Int.MaxValue + 1), DataType.Timestamp), Int32DataTypeObj) should be ( Left(ValidationError.OverflowError) ) + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray((BigInt(Long.MaxValue) * BigInt(Long.MaxValue)).toByteArray.length.toShort) ++ (BigInt(Long.MaxValue) * BigInt(Long.MaxValue)).toByteArray, DataType.BigInteger), Int32DataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) } property("test overflow to Amount") { - BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Long.MaxValue + 1).toByteArray.length.toShort) ++ BigInt(Long.MaxValue + 1).toByteArray, DataType.BigInteger), AmountDataTypeObj) should be ( + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray((BigInt(Long.MaxValue) + 1).toByteArray.length.toShort) ++ (BigInt(Long.MaxValue) + 1).toByteArray, DataType.BigInteger), AmountDataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + BasicOpcDiff.convertion(DataEntry((BigInt(Long.MaxValue) + 1).toByteArray, DataType.Amount), AmountDataTypeObj) should be ( Left(ValidationError.OverflowError) ) - BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue + 1), DataType.Amount), AmountDataTypeObj) should be ( + BasicOpcDiff.convertion(DataEntry((BigInt(Long.MaxValue) + 1).toByteArray, DataType.Timestamp), AmountDataTypeObj) should be ( Left(ValidationError.OverflowError) ) - BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue + 1), DataType.Timestamp), AmountDataTypeObj) should be ( + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray((BigInt(Long.MaxValue) * BigInt(Long.MaxValue)).toByteArray.length.toShort) ++ (BigInt(Long.MaxValue) * BigInt(Long.MaxValue)).toByteArray, DataType.BigInteger), AmountDataTypeObj) should be ( Left(ValidationError.OverflowError) ) } property("test overflow to Timestamp") { - BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray(BigInt(Long.MaxValue + 1).toByteArray.length.toShort) ++ BigInt(Long.MaxValue + 1).toByteArray, DataType.BigInteger), TimestampDataTypeObj) should be ( + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray((BigInt(Long.MaxValue) + 1).toByteArray.length.toShort) ++ (BigInt(Long.MaxValue) + 1).toByteArray, DataType.BigInteger), TimestampDataTypeObj) should be ( Left(ValidationError.OverflowError) ) - BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue + 1), DataType.Amount), TimestampDataTypeObj) should be ( + BasicOpcDiff.convertion(DataEntry((BigInt(Long.MaxValue) + 1).toByteArray, DataType.Amount), TimestampDataTypeObj) should be ( Left(ValidationError.OverflowError) ) - BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(Long.MaxValue + 1), DataType.Timestamp), TimestampDataTypeObj) should be ( + BasicOpcDiff.convertion(DataEntry((BigInt(Long.MaxValue) + 1).toByteArray, DataType.Timestamp), TimestampDataTypeObj) should be ( + Left(ValidationError.OverflowError) + ) + BasicOpcDiff.convertion(DataEntry(Shorts.toByteArray((BigInt(Long.MaxValue) * BigInt(Long.MaxValue)).toByteArray.length.toShort) ++ (BigInt(Long.MaxValue) * BigInt(Long.MaxValue)).toByteArray, DataType.BigInteger), TimestampDataTypeObj) should be ( Left(ValidationError.OverflowError) ) } - } From 09fb931bcf02dbcff3737e51369df4b94db53561 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 8 Feb 2021 12:04:40 +0800 Subject: [PATCH 252/391] fix bug --- .../scala/vsys/blockchain/state/StateWriter.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/StateWriter.scala b/src/main/scala/vsys/blockchain/state/StateWriter.scala index 1841e221c..edbc9a021 100644 --- a/src/main/scala/vsys/blockchain/state/StateWriter.scala +++ b/src/main/scala/vsys/blockchain/state/StateWriter.scala @@ -59,12 +59,14 @@ class StateWriterImpl(p: StateStorage, synchronizationToken: ReentrantReadWriteL if(stateSettings.txTypeAccountTxIds) { measureSizeLog("txTypeAccountTxIds")(blockDiff.txsDiff.txTypeAccountTxIds) { _.foreach { case ((txType, acc), txIds) => - val startIdxShift = sp().txTypeAccTxLengths.get(txTypeAccKey(txType, acc)).getOrElse(0) - txIds.reverse.foldLeft(startIdxShift) { case (shift, txId) => - sp().txTypeAccountTxIds.put(txTypeAccIndexKey(txType, acc, shift), txId) - shift + 1 + if (stateSettings.txContractTxIds || acc.bytes.arr(0) == Address.AddressVersion) { + val startIdxShift = sp().txTypeAccTxLengths.get(txTypeAccKey(txType, acc)).getOrElse(0) + txIds.reverse.foldLeft(startIdxShift) { case (shift, txId) => + sp().txTypeAccountTxIds.put(txTypeAccIndexKey(txType, acc, shift), txId) + shift + 1 + } + sp().txTypeAccTxLengths.put(txTypeAccKey(txType, acc), startIdxShift + txIds.length) } - sp().txTypeAccTxLengths.put(txTypeAccKey(txType, acc), startIdxShift + txIds.length) } } } From d456f9312f5b6e9db984eb1d533e61349603c0ed Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 9 Feb 2021 11:35:01 +0800 Subject: [PATCH 253/391] add escrow triggers --- .../blockchain/contract/ContractVEscrow.scala | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 1251c922e..bc99c4b17 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -1,16 +1,16 @@ package vsys.blockchain.contract import com.google.common.primitives.Ints -import vsys.blockchain.contract.ContractGen.{StateMap, StateVar, textualStateMap} +import vsys.blockchain.contract.ContractGen._ import vsys.blockchain.state._ import vsys.utils.serialization.Deser object ContractVEscrow { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(initTrigger, depositTrigger, withdrawTrigger), // Triggers Seq(), - Seq(), - Seq(), - Seq(), + stateVarSeq, // StateVars + stateMapSeq, // StateMaps Seq() ).explicitGet() @@ -74,12 +74,50 @@ object ContractVEscrow { stateMapOrderRefund, stateMapOrderRecipientRefund, stateMapOrderExpirationTime, stateMapOrderStatus, stateMapOrderRepDepositStatus, stateMapOrderJudgeDepositStatus, stateMapOrderSubmitStatus, stateMapOrderJudgeStatus, stateMapOrderRepLockedAmount, stateMapOrderJudgeLockedAmount)) - + // Initialization Trigger + val initId: Short = 0 + val initPara: Seq[String] = Seq("tokenId", "duration", "judgeDuration", + "signer") + val initDataType: Array[Byte] = Array(DataType.TokenId.id.toByte, DataType.Timestamp.id.toByte, DataType.Timestamp.id.toByte) + val initTriggerOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(3.toByte), + cdbvSet ++ Array(makerStateVar.index, 3.toByte), + cdbvSet ++ Array(judgeStateVar.index, 3.toByte), + cdbvSet ++ Array(tokenIdStateVar.index, 0.toByte), + cdbvSet ++ Array(durationStateVar.index, 1.toByte), + cdbvSet ++ Array(judgeDurationStateVar.index, 2.toByte) + ) + lazy val initTrigger: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initTriggerOpcs) + val initTextualBytes: Array[Byte] = textualFunc("init", Seq(), initPara) // Deposit Trigger + val depositId: Short = 1 + val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId", + "contractTokenId") + val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val depositTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(tokenIdStateVar.index, 3.toByte), + assertEqual ++ Array(2.toByte, 3.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 0.toByte, 1.toByte) + ) + lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) + val depositTextualBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) - // WithDraw Trigger + // Withdraw Trigger + val withdrawId: Short = 2 + val withdrawPara: Seq[String] = Seq("withdrawer", "amount", "tokenId", + "contractTokenId") + val withdrawDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) + val withdrawTriggerOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + cdbvrGet ++ Array(tokenIdStateVar.index, 3.toByte), + assertEqual ++ Array(2.toByte, 3.toByte), + cdbvMapValMinus ++ Array(contractBalanceMap.index, 0.toByte, 1.toByte) + ) + lazy val withdrawTrigger: Array[Byte] = getFunctionBytes(withdrawId, onWithDrawTriggerType, nonReturnType, withdrawDataType, withdrawTriggerOpcs) + val withdrawTextualBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) // Functions From c0d843187563645ee1642ba41dafc878dd8bad43 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 10 Feb 2021 22:00:48 +0800 Subject: [PATCH 254/391] modify tx api description --- .../vsys/api/http/TransactionsApiRoute.scala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala index 928a60656..5d262a2c3 100644 --- a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala +++ b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala @@ -46,11 +46,11 @@ case class TransactionsApiRoute( @Path("/count") @ApiOperation(value = "Count", - notes = "Get count of transactions where specified address has been involved. *This is a custom api, you need to enable it in configuration file.*", + notes = "Get count of transactions where specified address (wallet address or contract address) has been involved. *This is a custom api, you need to enable it in configuration file.*", httpMethod = "GET") @ApiImplicitParams(Array( - new ApiImplicitParam(name = "address", value = "wallet address ", required = true, dataType = "string", paramType = "query"), - new ApiImplicitParam(name = "txType", value = "transaction type", required = false, dataType = "integer", paramType = "query") + new ApiImplicitParam(name = "address", value = "Wallet address or contract address", required = true, dataType = "string", paramType = "query"), + new ApiImplicitParam(name = "txType", value = "Transaction type", required = false, dataType = "integer", paramType = "query") )) def transactionCount: Route = (path("count") & get) { parameters(('address, 'txType.?)) { (addressStr, txTypeStrOpt) => @@ -84,11 +84,11 @@ case class TransactionsApiRoute( @Path("/list") @ApiOperation(value = "List", - notes = "Get list of transactions where specified address has been involved. *This is a custom api, you need to enable it in configuration file.*", + notes = "Get list of transactions where specified address (wallet address or contract address) has been involved. *This is a custom api, you need to enable it in configuration file.*", httpMethod = "GET") @ApiImplicitParams(Array( - new ApiImplicitParam(name = "address", value = "wallet address ", required = true, dataType = "string", paramType = "query"), - new ApiImplicitParam(name = "txType", value = "transaction type ", required = false, dataType = "integer", paramType = "query"), + new ApiImplicitParam(name = "address", value = "Wallet address or contract address", required = true, dataType = "string", paramType = "query"), + new ApiImplicitParam(name = "txType", value = "Transaction type", required = false, dataType = "integer", paramType = "query"), new ApiImplicitParam(name = "limit", value = "Specified number of records to be returned", required = true, dataType = "integer", paramType = "query"), new ApiImplicitParam(name = "offset", value = "Specified number of records offset", required = false, dataType = "integer", paramType = "query") )) @@ -129,9 +129,9 @@ case class TransactionsApiRoute( } @Path("/address/{address}/limit/{limit}") - @ApiOperation(value = "Address", notes = "Get list of transactions where specified address has been involved", httpMethod = "GET") + @ApiOperation(value = "Address", notes = "Get list of transactions where specified address (wallet address or contract address) has been involved", httpMethod = "GET") @ApiImplicitParams(Array( - new ApiImplicitParam(name = "address", value = "Wallet address ", required = true, dataType = "string", paramType = "path"), + new ApiImplicitParam(name = "address", value = "Wallet address or contract address", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "limit", value = "Specified number of records to be returned", required = true, dataType = "integer", paramType = "path") )) //remove after all related productions being updated From 360f30b8c2755ad422fa2b431e9dae010dd6a436 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 16 Feb 2021 11:14:46 +0800 Subject: [PATCH 255/391] add supersede and create func --- .../blockchain/contract/ContractVEscrow.scala | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index bc99c4b17..ee576d059 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -1,6 +1,6 @@ package vsys.blockchain.contract -import com.google.common.primitives.Ints +import com.google.common.primitives.{Ints, Longs} import vsys.blockchain.contract.ContractGen._ import vsys.blockchain.state._ import vsys.utils.serialization.Deser @@ -120,6 +120,58 @@ object ContractVEscrow { val withdrawTextualBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) // Functions + // Supersede + val supersedeId: Short = 0 + val supersedePara: Seq[String] = Seq("newJudge", + "maker") + val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val supersedeOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(makerStateVar.index, 1.toByte), + assertSigner ++ Array(1.toByte), + cdbvSet ++ Array(judgeStateVar.index, 0.toByte)) + lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) + val supersedeTextualBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) + + // Create Order Function + val createId: Short = 0 + val createPara: Seq[String] = Seq("recipient", "amount", "repDeposit", "judgeDeposit", "fee", "refund", "expirationTime", + "caller", "orderId", "repAmount", "needToDeposit", "totalDeposit", "repRefund", + "valueTrue", "valueFalse", "amountZero") + val createDataType: Array[Byte] = Array(DataType.Address.id.toByte) ++ + Array.fill[Byte](5)(DataType.Amount.id.toByte) ++ + Array(DataType.Timestamp.id.toByte) + val createOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(7.toByte), + loadTransactionId ++ Array(8.toByte), + cdbvMapValMinus ++ Array(contractBalanceMap.index, 7.toByte, 1.toByte), + cdbvMapSet ++ Array(orderPayerMap.index, 8.toByte, 7.toByte), + cdbvMapSet ++ Array(orderRecipientMap.index, 8.toByte, 0.toByte), + cdbvMapSet ++ Array(orderAmountMap.index, 8.toByte, 1.toByte), + cdbvMapSet ++ Array(orderRecipientDepositMap.index, 8.toByte, 2.toByte), + cdbvMapSet ++ Array(orderJudgeDepositMap.index, 8.toByte, 3.toByte), + cdbvMapSet ++ Array(orderFeeMap.index, 8.toByte, 4.toByte), + basicMinus ++ Array(1.toByte, 4.toByte, 9.toByte), + cdbvMapSet ++ Array(orderRecipientAmountMap.index, 8.toByte, 9.toByte), + basicAdd ++ Array(2.toByte, 3.toByte, 10.toByte), + basicAdd ++ Array(10.toByte, 1.toByte, 11.toByte), + basicMinus ++ Array(11.toByte, 5.toByte, 12.toByte), + cdbvMapSet ++ Array(orderRefundMap.index, 8.toByte, 5.toByte), + cdbvMapSet ++ Array(orderRecipientRefundMap.index, 8.toByte, 12.toByte), + cdbvMapSet ++ Array(orderExpirationTimeMap.index, 8.toByte, 6.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(13.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 8.toByte, 13.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(14.toByte), + cdbvMapSet ++ Array(orderRepDepositStatusMap.index, 8.toByte, 14.toByte), + cdbvMapSet ++ Array(orderJudgeDepositStatusMap.index, 8.toByte, 14.toByte), + cdbvMapSet ++ Array(orderSubmitStatusMap.index, 8.toByte, 14.toByte), + cdbvMapSet ++ Array(orderJudgeStatusMap.index, 8.toByte, 14.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(0L), DataType.Amount).bytes ++ Array(15.toByte), + cdbvMapSet ++ Array(orderRepLockedAmountMap.index, 8.toByte, 15.toByte), + cdbvMapSet ++ Array(orderJudgeLockedAmountMap.index, 8.toByte, 15.toByte) + ) + lazy val createFunc: Array[Byte] = getFunctionBytes(createId, publicFuncType, nonReturnType, createDataType, createOpcs) + val createTextualBytes: Array[Byte] = textualFunc("create", Seq(), createPara) + // Textual } \ No newline at end of file From 7e2a281ec9a2dd7d2265438f92bfb31435a7c92c Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 16 Feb 2021 19:55:54 +0800 Subject: [PATCH 256/391] fix bug --- src/main/scala/vsys/blockchain/state/StateWriter.scala | 2 +- .../scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/StateWriter.scala b/src/main/scala/vsys/blockchain/state/StateWriter.scala index edbc9a021..3ee1d9ad1 100644 --- a/src/main/scala/vsys/blockchain/state/StateWriter.scala +++ b/src/main/scala/vsys/blockchain/state/StateWriter.scala @@ -49,7 +49,7 @@ class StateWriterImpl(p: StateStorage, synchronizationToken: ReentrantReadWriteL val startIdxShift = sp().accountTransactionsLengths.get(acc.bytes).getOrElse(0) txIds.reverse.foldLeft(startIdxShift) { case (shift, txId) => sp().accountTransactionIds.put(accountIndexKey(acc, shift), txId) - shift + 1 + shift + 1 } sp().accountTransactionsLengths.put(acc.bytes, startIdxShift + txIds.length) } diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala index f35db8227..7c9db7a78 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/TDBAOpcDiff.scala @@ -131,12 +131,12 @@ object TDBAOpcDiff extends OpcDiffer { // relatedContract needed for { senderCallDiff <- getTriggerCallOpcDiff(context, OpcDiff.empty, sender, recipient, amount, tokenIdDataEntry, CallType.Trigger, 2) - senderRelatedAddress = if (sender.dataType == DataType.Address) Map(Account.fromBytes(sender.data,0).explicitGet()._1 -> true) else Map[Account, Boolean]() + senderRelatedAddress = Map[Account, Boolean](Account.fromBytes(sender.data,0).explicitGet()._1 -> true) senderDiff = OpcDiff(relatedAddress = senderRelatedAddress, tokenAccountBalance = Map(senderBalanceKey -> -transferAmount)) senderTotalDiff = OpcDiff.opcDiffMonoid.combine(senderCallDiff, senderDiff) recipientCallDiff <- getTriggerCallOpcDiff(context, senderTotalDiff, sender, recipient, amount, tokenIdDataEntry, CallType.Trigger, 1) - recipientRelatedAddress = if (recipient.dataType == DataType.Address) Map(Account.fromBytes(recipient.data,0).explicitGet()._1 -> true) else Map[Account, Boolean]() + recipientRelatedAddress = Map[Account, Boolean](Account.fromBytes(recipient.data,0).explicitGet()._1 -> true) recipientDiff = OpcDiff(relatedAddress = recipientRelatedAddress, tokenAccountBalance = Map(recipientBalanceKey -> transferAmount)) returnDiff = Monoid.combineAll(Seq(senderTotalDiff, recipientCallDiff, recipientDiff)) From e6b1b8d2cec9082f603f8cc5aaab1e9a9326d809 Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 22 Feb 2021 11:44:21 +0800 Subject: [PATCH 257/391] add order deposit funcs --- .../blockchain/contract/ContractVEscrow.scala | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index ee576d059..49d40a2db 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -133,7 +133,7 @@ object ContractVEscrow { val supersedeTextualBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) // Create Order Function - val createId: Short = 0 + val createId: Short = 1 val createPara: Seq[String] = Seq("recipient", "amount", "repDeposit", "judgeDeposit", "fee", "refund", "expirationTime", "caller", "orderId", "repAmount", "needToDeposit", "totalDeposit", "repRefund", "valueTrue", "valueFalse", "amountZero") @@ -172,6 +172,48 @@ object ContractVEscrow { lazy val createFunc: Array[Byte] = getFunctionBytes(createId, publicFuncType, nonReturnType, createDataType, createOpcs) val createTextualBytes: Array[Byte] = textualFunc("create", Seq(), createPara) + // Order Deposit Common + private def depositCommonOpcs(isCallerJudge: Boolean, orderDepositStatusIndex: Byte, orderDepositAmountIndex: Byte, orderLockedAmountIndex: Byte): Seq[Array[Byte]] = { + val tmp :Seq[Array[Byte]] = Seq( + assertCaller ++ Array(1.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), + assertTrue ++ Array(2.toByte), + cdbvrMapGet ++ Array(orderDepositStatusIndex, 0.toByte, 3.toByte), + assertTrue ++ Array(3.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(4.toByte), + assertEqual ++ Array(3.toByte, 4.toByte), + cdbvrMapGet ++ Array(orderDepositAmountIndex, 0.toByte, 5.toByte), + cdbvMapValMinus ++ Array(contractBalanceMap.index, 1.toByte, 5.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + cdbvMapSet ++ Array(orderDepositStatusIndex, 0.toByte, 6.toByte), + cdbvMapSet ++ Array(orderLockedAmountIndex, 0.toByte, 5.toByte) + ) + if (isCallerJudge) { + Seq(cdbvrGet ++ Array(judgeStateVar.index, 1.toByte)) ++ tmp + } else { + Seq(cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte)) ++ tmp + } + } + + // Recipient Deposit Function + val recipientDepositId: Short = 1 + val recipientDepositPara: Seq[String] = Seq("orderId") ++ + Seq("recipient", "orderStatus", "depositStatus", "valueFalse", "amount", "valueTrue") + val recipientDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + val recipientDepositOpcs: Seq[Array[Byte]] = depositCommonOpcs(false, orderRepDepositStatusMap.index, + orderRecipientDepositMap.index, orderRepLockedAmountMap.index) + lazy val recipientDepositFunc: Array[Byte] = getFunctionBytes(recipientDepositId, publicFuncType, nonReturnType, recipientDepositDataType, recipientDepositOpcs) + val recipientDepositTextualBytes: Array[Byte] = textualFunc("recipientDeposit", Seq(), recipientDepositPara) + + // Judge Deposit Function + val judgeDepositId: Short = 2 + val judgeDepositPara: Seq[String] = Seq("orderId") ++ + Seq("judge", "orderStatus", "depositStatus", "valueFalse", "amount", "valueTrue") + val judgeDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + val judgeDepositOpcs: Seq[Array[Byte]] = depositCommonOpcs(true, orderJudgeDepositStatusMap.index, + orderJudgeDepositMap.index, orderJudgeLockedAmountMap.index) + lazy val judgeDepositFunc: Array[Byte] = getFunctionBytes(judgeDepositId, publicFuncType, nonReturnType, judgeDepositDataType, judgeDepositOpcs) + val judgeDepositTextualBytes: Array[Byte] = textualFunc("judgeDeposit", Seq(), judgeDepositPara) // Textual } \ No newline at end of file From c6c46de3a89d72b576f69df6e84a4ebe4cd511ef Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 23 Feb 2021 11:49:33 +0800 Subject: [PATCH 258/391] add order cancel funcs --- .../blockchain/contract/ContractGen.scala | 4 ++ .../blockchain/contract/ContractVEscrow.scala | 52 +++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractGen.scala b/src/main/scala/vsys/blockchain/contract/ContractGen.scala index 4aee6576e..99a2f2a0f 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractGen.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractGen.scala @@ -66,6 +66,10 @@ object ContractGen { val basicConstantGet = Array(11.toByte, 8.toByte) val basicSqrtBigint = Array(11.toByte, 9.toByte) val basicConvert = Array(11.toByte, 10.toByte) + val basicAnd = Array(11.toByte, 11.toByte) + val basicOr = Array(11.toByte, 12.toByte) + val basicXor = Array(11.toByte, 13.toByte) + val basicNot = Array(11.toByte, 14.toByte) val conditionIf = Array(12.toByte, 1.toByte) val conditionIfElse = Array(12.toByte, 1.toByte) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 49d40a2db..71bd15357 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -184,7 +184,7 @@ object ContractVEscrow { assertEqual ++ Array(3.toByte, 4.toByte), cdbvrMapGet ++ Array(orderDepositAmountIndex, 0.toByte, 5.toByte), cdbvMapValMinus ++ Array(contractBalanceMap.index, 1.toByte, 5.toByte), - basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(6.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), cdbvMapSet ++ Array(orderDepositStatusIndex, 0.toByte, 6.toByte), cdbvMapSet ++ Array(orderLockedAmountIndex, 0.toByte, 5.toByte) ) @@ -196,7 +196,7 @@ object ContractVEscrow { } // Recipient Deposit Function - val recipientDepositId: Short = 1 + val recipientDepositId: Short = 2 val recipientDepositPara: Seq[String] = Seq("orderId") ++ Seq("recipient", "orderStatus", "depositStatus", "valueFalse", "amount", "valueTrue") val recipientDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) @@ -206,7 +206,7 @@ object ContractVEscrow { val recipientDepositTextualBytes: Array[Byte] = textualFunc("recipientDeposit", Seq(), recipientDepositPara) // Judge Deposit Function - val judgeDepositId: Short = 2 + val judgeDepositId: Short = 3 val judgeDepositPara: Seq[String] = Seq("orderId") ++ Seq("judge", "orderStatus", "depositStatus", "valueFalse", "amount", "valueTrue") val judgeDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) @@ -215,5 +215,51 @@ object ContractVEscrow { lazy val judgeDepositFunc: Array[Byte] = getFunctionBytes(judgeDepositId, publicFuncType, nonReturnType, judgeDepositDataType, judgeDepositOpcs) val judgeDepositTextualBytes: Array[Byte] = textualFunc("judgeDeposit", Seq(), judgeDepositPara) + // Order Cancel Common + val cancelCommonPara: Seq[String] = Seq("orderId") ++ + Seq("payer", "recipient", "judge", "orderStatus", "repDepositStatus", "judgeDepositStatus", + "depositStatus", "valueFalse", "amount", "recipientAmount", "judgeAmount") + val cancelCommonDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + private def cancelCommonOpcs(callerIndex: Byte): Seq[Array[Byte]] = { + Seq( + cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 1.toByte), + cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 2.toByte), + cdbvrGet ++ Array(judgeStateVar.index, 3.toByte), + assertCaller ++ Array(callerIndex), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte), + assertTrue ++ Array(4.toByte), + cdbvrMapGet ++ Array(orderRepDepositStatusMap.index, 0.toByte, 5.toByte), + cdbvrMapGet ++ Array(orderJudgeDepositStatusMap.index, 0.toByte, 6.toByte), + basicAnd ++ Array(5.toByte, 6.toByte, 7.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(8.toByte), + assertEqual ++ Array(7.toByte, 8.toByte), + cdbvrMapGet ++ Array(orderAmountMap.index, 0.toByte, 9.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 1.toByte, 9.toByte), + cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 2.toByte, 10.toByte), + cdbvrMapGet ++ Array(orderJudgeLockedAmountMap.index, 0.toByte, 11.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 3.toByte, 11.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 8.toByte) + ) + } + + // Payer Cancel Function + val payerCancelId: Short = 4 + val payerCancelOpcs: Seq[Array[Byte]] = cancelCommonOpcs(1.toByte) + lazy val payerCancelFunc: Array[Byte] = getFunctionBytes(payerCancelId, publicFuncType, nonReturnType, cancelCommonDataType, payerCancelOpcs) + val payerCancelTextualBytes: Array[Byte] = textualFunc("payerCancel", Seq(), cancelCommonPara) + + // Recipient Cancel Function + val recipientCancelId: Short = 5 + val recipientCancelOpcs: Seq[Array[Byte]] = cancelCommonOpcs(2.toByte) + lazy val recipientCancelFunc: Array[Byte] = getFunctionBytes(recipientCancelId, publicFuncType, nonReturnType, cancelCommonDataType, recipientCancelOpcs) + val recipientCancelTextualBytes: Array[Byte] = textualFunc("recipientCancel", Seq(), cancelCommonPara) + + // Judge Cancel Function + val judgeCancelId: Short = 6 + val judgeCancelOpcs: Seq[Array[Byte]] = cancelCommonOpcs(3.toByte) + lazy val judgeCancelFunc: Array[Byte] = getFunctionBytes(judgeCancelId, publicFuncType, nonReturnType, cancelCommonDataType, judgeCancelOpcs) + val judgeCancelTextualBytes: Array[Byte] = textualFunc("judgeCancel", Seq(), cancelCommonPara) + // Textual } \ No newline at end of file From de900a1a01c509bf347959ee465c590efe62d791 Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 24 Feb 2021 11:31:29 +0800 Subject: [PATCH 259/391] add submit work func --- .../blockchain/contract/ContractVEscrow.scala | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 71bd15357..40a6974bd 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -261,5 +261,38 @@ object ContractVEscrow { lazy val judgeCancelFunc: Array[Byte] = getFunctionBytes(judgeCancelId, publicFuncType, nonReturnType, cancelCommonDataType, judgeCancelOpcs) val judgeCancelTextualBytes: Array[Byte] = textualFunc("judgeCancel", Seq(), cancelCommonPara) + // Submit Work Function + val submitWorkId: Short = 7 + val submitWorkPara: Seq[String] = Seq("orderId") ++ + Seq("recipient", "orderStatus", "repDepositStatus", "judgeDepositStatus", "depositStatus", + "currentTime", "expirationTime", "isValidTime", "valueFalse", "submitStatus", "duration", + "time", "updateTime", "valueTrue") + val submitWorkDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + val submitWorkOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), + assertCaller ++ Array(1.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), + assertTrue ++ Array(2.toByte), + cdbvrMapGet ++ Array(orderRepDepositStatusMap.index, 0.toByte, 3.toByte), + cdbvrMapGet ++ Array(orderJudgeDepositStatusMap.index, 0.toByte, 4.toByte), + basicAnd ++ Array(3.toByte, 4.toByte, 5.toByte), + assertTrue ++ Array(5.toByte), + loadTimestamp ++ Array(6.toByte), + cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 7.toByte), + compareGreater ++ Array(7.toByte, 6.toByte, 8.toByte), + assertTrue ++Array(8.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(9.toByte), + cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 10.toByte), + assertEqual ++ Array(9.toByte, 10.toByte), + cdbvrGet ++ Array(durationStateVar.index, 11.toByte), + basicAdd ++ Array(6.toByte, 11.toByte, 12.toByte), + basicMax ++ Array(12.toByte, 7.toByte, 13.toByte), + cdbvMapSet ++ Array(orderExpirationTimeMap.index, 0.toByte, 13.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(14.toByte), + cdbvMapSet ++ Array(orderSubmitStatusMap.index, 0.toByte, 14.toByte) + ) + lazy val submitWorkFunc: Array[Byte] = getFunctionBytes(submitWorkId, publicFuncType, nonReturnType, submitWorkDataType, submitWorkOpcs) + val submitWorkTextualBytes: Array[Byte] = textualFunc("submitWork", Seq(), submitWorkPara) + // Textual } \ No newline at end of file From b1f5fef3dc823114f7b3174cd393935497120dfa Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Mon, 1 Mar 2021 14:53:47 +0800 Subject: [PATCH 260/391] Fix the returning type of Public key --- src/main/scala/vsys/blockchain/contract/DataType.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataType.scala b/src/main/scala/vsys/blockchain/contract/DataType.scala index 0db70f415..9867ca5ad 100644 --- a/src/main/scala/vsys/blockchain/contract/DataType.scala +++ b/src/main/scala/vsys/blockchain/contract/DataType.scala @@ -47,7 +47,7 @@ object DataType extends Enumeration { maxLen = KeyLength, deserializer = PublicKeyAccount(_), serializer = p => p.publicKey, - jsonifier = p => Json.toJson(p.address), + jsonifier = p => Json.toJson(Base58.encode(p.publicKey)), extValidator = _ => true) val Address = DataTypeVal[vsys.account.Address](2, From fb46c473f1a20e8fb5e4a71687ee10dae8ea6c14 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 2 Mar 2021 11:27:08 +0800 Subject: [PATCH 261/391] add approve work func --- .../blockchain/contract/ContractVEscrow.scala | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 40a6974bd..088901db1 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -294,5 +294,39 @@ object ContractVEscrow { lazy val submitWorkFunc: Array[Byte] = getFunctionBytes(submitWorkId, publicFuncType, nonReturnType, submitWorkDataType, submitWorkOpcs) val submitWorkTextualBytes: Array[Byte] = textualFunc("submitWork", Seq(), submitWorkPara) + // Approve Work Function + val approveWorkId: Short = 8 + val approveWorkPara: Seq[String] = Seq("orderId") ++ + Seq("payer", "orderStatus", "isSubmit", "currentTime", "expirationTime", "isValidTime", + "recipient", "judge", "workAmount", "recipientLocked", "recipientAmount", + "fee", "judgeLocked", "judgeAmount", "valueFalse") + val approveWorkDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + val approveWorkOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), + assertCaller ++ Array(1.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), + assertTrue ++ Array(2.toByte), + cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 3.toByte), + assertTrue ++ Array(3.toByte), + loadTimestamp ++ Array(4.toByte), + cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 5.toByte), + compareGreater ++ Array(5.toByte, 4.toByte, 6.toByte), + assertTrue ++Array(6.toByte), + cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 7.toByte), + cdbvrGet ++ Array(judgeStateVar.index, 0.toByte, 8.toByte), + cdbvrMapGet ++ Array(orderRecipientAmountMap.index, 0.toByte, 9.toByte), + cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), + basicAdd ++ Array(9.toByte, 10.toByte, 11.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 7.toByte, 11.toByte), + cdbvrMapGet ++ Array(orderFeeMap.index, 0.toByte, 12.toByte), + cdbvrMapGet ++ Array(orderJudgeLockedAmountMap.index, 0.toByte, 13toByte), + basicAdd ++ Array(12.toByte, 13.toByte, 14.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 8.toByte, 14.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(15.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 15.toByte) + ) + lazy val approveWorkFunc: Array[Byte] = getFunctionBytes(approveWorkId, publicFuncType, nonReturnType, approveWorkDataType, approveWorkOpcs) + val approveWorkTextualBytes: Array[Byte] = textualFunc("approveWork", Seq(), approveWorkPara) + // Textual } \ No newline at end of file From d003c0bb246aa1caf0682b867dd8a18d6275a3bb Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 4 Mar 2021 10:24:37 +0800 Subject: [PATCH 262/391] add apply to judge func --- .../blockchain/contract/ContractVEscrow.scala | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 088901db1..d5e5426ef 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -328,5 +328,35 @@ object ContractVEscrow { lazy val approveWorkFunc: Array[Byte] = getFunctionBytes(approveWorkId, publicFuncType, nonReturnType, approveWorkDataType, approveWorkOpcs) val approveWorkTextualBytes: Array[Byte] = textualFunc("approveWork", Seq(), approveWorkPara) + // Apply to Judge Function + val applyToJudgeId: Short = 9 + val applyToJudgePara: Seq[String] = Seq("orderId") ++ + Seq("payer", "orderStatus", "isSubmit", "currentTime", "expirationTime", "isValidTime", + "judgeStatus", "valueFalse", "judgeDuration", "time", "updateTime", "valueTrue") + val applyToJudgeDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + val applyToJudgeOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), + assertCaller ++ Array(1.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), + assertTrue ++ Array(2.toByte), + cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 3.toByte), + assertTrue ++ Array(3.toByte), + loadTimestamp ++ Array(4.toByte), + cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 5.toByte), + compareGreater ++ Array(5.toByte, 4.toByte, 6.toByte), + assertTrue ++Array(6.toByte), + cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 7.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(8.toByte), + assertEqual ++ Array(7.toByte, 8.toByte), + cdbvrGet ++ Array(judgeDurationStateVar.index, 9.toByte), + basicAdd ++ Array(4.toByte, 9.toByte, 10.toByte), + basicMax ++ Array(10.toByte, 5.toByte, 11.toByte), + cdbvMapSet ++ Array(orderExpirationTimeMap.index, 0.toByte, 11.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(12.toByte), + cdbvMapSet ++ Array(orderJudgeStatusMap.index, 0.toByte, 12.toByte) + ) + lazy val applyToJudgeFunc: Array[Byte] = getFunctionBytes(applyToJudgeId, publicFuncType, nonReturnType, applyToJudgeDataType, applyToJudgeOpcs) + val applyToJudgeTextualBytes: Array[Byte] = textualFunc("applyToJudge", Seq(), applyToJudgePara) + // Textual } \ No newline at end of file From 5a87fc860c31da8b04b5e8de2551e1a05e7a0573 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 4 Mar 2021 10:46:09 +0800 Subject: [PATCH 263/391] add judge func --- .../blockchain/contract/ContractVEscrow.scala | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index d5e5426ef..456aa2b48 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -344,7 +344,7 @@ object ContractVEscrow { loadTimestamp ++ Array(4.toByte), cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 5.toByte), compareGreater ++ Array(5.toByte, 4.toByte, 6.toByte), - assertTrue ++Array(6.toByte), + assertTrue ++ Array(6.toByte), cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 7.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(8.toByte), assertEqual ++ Array(7.toByte, 8.toByte), @@ -358,5 +358,42 @@ object ContractVEscrow { lazy val applyToJudgeFunc: Array[Byte] = getFunctionBytes(applyToJudgeId, publicFuncType, nonReturnType, applyToJudgeDataType, applyToJudgeOpcs) val applyToJudgeTextualBytes: Array[Byte] = textualFunc("applyToJudge", Seq(), applyToJudgePara) + // Judge Function + val judgeId: Short = 10 + val judgePara: Seq[String] = Seq("orderId", "payerAmount", "recipientAmount") ++ + Seq("judge", "orderStatus", "currentTime", "expirationTime", "isValidTime", + "judgeStatus", "payToRep", "recipientLocked", "totalToPay", "totalArrange", + "fee", "judgeLocked", "judgeAmount", "valueFalse") + val judgeDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) + val judgeOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(judgeStateVar.index, 3.toByte), + assertCaller ++ Array(3.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte), + assertTrue ++ Array(4.toByte), + loadTimestamp ++ Array(5.toByte), + cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 6.toByte), + compareGreater ++ Array(6.toByte, 5.toByte, 7.toByte), + assertTrue ++ Array(7.toByte), + cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + cdbvrMapGet ++ Array(orderRecipientAmountMap.index, 0.toByte, 9.toByte), + cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), + basicAdd ++ Array(9.toByte, 10.toByte, 11.toByte), + basicAdd ++ Array(1.toByte, 2.toByte, 12.toByte), + assertEqual ++ Array(11.toByte, 12.toByte), + cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 13.toByte), + cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 14.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 13.toByte, 1.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 14.toByte, 2.toByte), + cdbvrMapGet ++ Array(orderFeeMap.index, 0.toByte, 15.toByte), + cdbvrMapGet ++ Array(orderJudgeLockedAmountMap.index, 0.toByte, 16.toByte), + basicAdd ++ Array(15.toByte, 16.toByte, 17.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 3.toByte, 17.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(18.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 18.toByte) + ) + lazy val judgeFunc: Array[Byte] = getFunctionBytes(judgeId, publicFuncType, nonReturnType, judgeDataType, judgeOpcs) + val judgeTextualBytes: Array[Byte] = textualFunc("judge", Seq(), judgePara) + // Textual } \ No newline at end of file From 5345a01b3682641f813db416a0abe74c3baeb1ff Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 4 Mar 2021 11:18:56 +0800 Subject: [PATCH 264/391] add submit penalty func --- .../blockchain/contract/ContractVEscrow.scala | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 456aa2b48..b05a6ff8d 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -395,5 +395,39 @@ object ContractVEscrow { lazy val judgeFunc: Array[Byte] = getFunctionBytes(judgeId, publicFuncType, nonReturnType, judgeDataType, judgeOpcs) val judgeTextualBytes: Array[Byte] = textualFunc("judge", Seq(), judgePara) + // Submit Penalty Function + val submitPenaltyId: Short = 10 + val submitPenaltyPara: Seq[String] = Seq("orderId") ++ + Seq("payer", "orderStatus", "valueFalse", "isSubmit", + "currentTime", "expirationTime", "isExpired", + "judge", "workAmount", "recipientLocked", "penaltyAmount", + "fee", "judgeLocked", "judgeAmount") + val submitPenaltyDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + val submitPenaltyOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 1.toByte), + assertCaller ++ Array(1.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), + assertTrue ++ Array(2.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(3.toByte), + cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 4.toByte), + assertEqual ++ Array(3.toByte, 4.toByte), + loadTimestamp ++ Array(5.toByte), + cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 6.toByte), + compareGreater ++ Array(5.toByte, 6.toByte, 7.toByte), + assertTrue ++ Array(7.toByte), + cdbvrGet ++ Array(judgeStateVar.index, 8.toByte), + cdbvrMapGet ++ Array(orderRecipientAmountMap.index, 0.toByte, 9.toByte), + cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), + basicAdd ++ Array(9.toByte, 10.toByte, 11.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 1.toByte, 11.toByte), + cdbvrMapGet ++ Array(orderFeeMap.index, 0.toByte, 12.toByte), + cdbvrMapGet ++ Array(orderJudgeLockedAmountMap.index, 0.toByte, 13.toByte), + basicAdd ++ Array(12.toByte, 13.toByte, 14.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 8.toByte, 14.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 3.toByte) + ) + lazy val submitPenaltyFunc: Array[Byte] = getFunctionBytes(submitPenaltyId, publicFuncType, nonReturnType, submitPenaltyDataType, submitPenaltyOpcs) + val submitPenaltyTextualBytes: Array[Byte] = textualFunc("submitPenalty", Seq(), submitPenaltyPara) + // Textual } \ No newline at end of file From 4fafc2b631aca8288106cbce830e7f7fe50f201a Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 5 Mar 2021 11:06:48 +0800 Subject: [PATCH 265/391] add refund func --- .../blockchain/contract/ContractVEscrow.scala | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index b05a6ff8d..66428fa64 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -396,7 +396,7 @@ object ContractVEscrow { val judgeTextualBytes: Array[Byte] = textualFunc("judge", Seq(), judgePara) // Submit Penalty Function - val submitPenaltyId: Short = 10 + val submitPenaltyId: Short = 11 val submitPenaltyPara: Seq[String] = Seq("orderId") ++ Seq("payer", "orderStatus", "valueFalse", "isSubmit", "currentTime", "expirationTime", "isExpired", @@ -429,5 +429,45 @@ object ContractVEscrow { lazy val submitPenaltyFunc: Array[Byte] = getFunctionBytes(submitPenaltyId, publicFuncType, nonReturnType, submitPenaltyDataType, submitPenaltyOpcs) val submitPenaltyTextualBytes: Array[Byte] = textualFunc("submitPenalty", Seq(), submitPenaltyPara) + // Order Refund Common + val refundCommonPara: Seq[String] = Seq("orderId") ++ + Seq("payer", "recipient", "orderStatus", "judgeStatus", "currentTime", "expirationTime", "isExpired", + "recipientRefund", "payerRefund", "valueFalse") + val refundCommonDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + private def refundCommonOpcs(callerIndex: Byte): Seq[Array[Byte]] = { + Seq( + cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 1.toByte), + cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 2.toByte), + assertCaller ++ Array(callerIndex), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 3.toByte), + assertTrue ++ Array(3.toByte), + cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 4.toByte), + assertTrue ++ Array(4.toByte), + loadTimestamp ++ Array(5.toByte), + cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 6.toByte), + compareGreater ++ Array(5.toByte, 6.toByte, 7.toByte), + assertTrue ++ Array(7.toByte), + cdbvrMapGet ++ Array(orderRecipientRefundMap.index, 0.toByte, 8.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 2.toByte, 8.toByte), + cdbvrMapGet ++ Array(orderRefundMap.index, 0.toByte, 9.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 1.toByte, 9.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(10.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 10.toByte) + ) + } + + // Payer Refund Function + val payerRefundId: Short = 12 + val payerRefundOpcs: Seq[Array[Byte]] = refundCommonOpcs(1.toByte) + lazy val payerRefundFunc: Array[Byte] = getFunctionBytes(payerRefundId, publicFuncType, nonReturnType, refundCommonDataType, payerRefundOpcs) + val payerRefundTextualBytes: Array[Byte] = textualFunc("payerRefund", Seq(), refundCommonPara) + + // Payer Refund Function + val recipientRefundId: Short = 13 + val recipientRefundOpcs: Seq[Array[Byte]] = refundCommonOpcs(2.toByte) + lazy val recipientRefundFunc: Array[Byte] = getFunctionBytes(recipientRefundId, publicFuncType, nonReturnType, refundCommonDataType, recipientRefundOpcs) + val recipientRefundTextualBytes: Array[Byte] = textualFunc("recipientRefund", Seq(), refundCommonPara) + + // Textual } \ No newline at end of file From 61d76b6acd7ec2e2f3d6830425668cc779f8d77c Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 5 Mar 2021 11:40:16 +0800 Subject: [PATCH 266/391] add collect func --- .../blockchain/contract/ContractVEscrow.scala | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 66428fa64..8af590131 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -468,6 +468,40 @@ object ContractVEscrow { lazy val recipientRefundFunc: Array[Byte] = getFunctionBytes(recipientRefundId, publicFuncType, nonReturnType, refundCommonDataType, recipientRefundOpcs) val recipientRefundTextualBytes: Array[Byte] = textualFunc("recipientRefund", Seq(), refundCommonPara) - + // Collect Function + val collectId: Short = 13 + val collectPara: Seq[String] = Seq("orderId") ++ + Seq("recipient", "orderStatus", "isSubmit", "valueFalse", "judgeStatus", + "currentTime", "expirationTime", "isExpired", + "judge", "workAmount", "recipientLocked", "recipientAmount", "fee", "judgerLocked", "judgerAmount") + val collectDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + val collectOpcs: Seq[Array[Byte]] = Seq( + cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), + assertCaller ++ Array(1.toByte), + cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), + assertCaller ++ Array(2.toByte), + cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 3.toByte), + assertCaller ++ Array(3.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(4.toByte), + cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 5.toByte), + assertEqual ++ Array(4.toByte, 5.toByte), + loadTimestamp ++ Array(6.toByte), + cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 7.toByte), + compareGreater ++ Array(6.toByte, 7.toByte, 8.toByte), + assertTrue ++ Array(8.toByte), + cdbvrGet ++ Array(judgeStateVar.index, 9.toByte), + cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), + cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 11.toByte), + basicAdd ++ Array(10.toByte, 11.toByte, 12.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 1.toByte, 12.toByte), + cdbvrMapGet ++ Array(orderFeeMap.index, 0.toByte, 13.toByte), + cdbvrMapGet ++ Array(orderJudgeLockedAmountMap.index, 0.toByte, 14.toByte), + basicAdd ++ Array(13.toByte, 14.toByte, 15.toByte), + cdbvMapValAdd ++ Array(contractBalanceMap.index, 9.toByte, 15.toByte), + cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte) + ) + lazy val collectFunc: Array[Byte] = getFunctionBytes(collectId, publicFuncType, nonReturnType, collectDataType, collectOpcs) + val collectTextualBytes: Array[Byte] = textualFunc("collect", Seq(), collectPara) + // Textual } \ No newline at end of file From 4d3966a9a9f9723e117bfdaf9fc1acf47c4196cb Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 5 Mar 2021 11:55:19 +0800 Subject: [PATCH 267/391] add textual --- .../scala/vsys/blockchain/contract/ContractVEscrow.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 8af590131..31d6c0496 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -469,7 +469,7 @@ object ContractVEscrow { val recipientRefundTextualBytes: Array[Byte] = textualFunc("recipientRefund", Seq(), refundCommonPara) // Collect Function - val collectId: Short = 13 + val collectId: Short = 14 val collectPara: Seq[String] = Seq("orderId") ++ Seq("recipient", "orderStatus", "isSubmit", "valueFalse", "judgeStatus", "currentTime", "expirationTime", "isExpired", @@ -502,6 +502,11 @@ object ContractVEscrow { ) lazy val collectFunc: Array[Byte] = getFunctionBytes(collectId, publicFuncType, nonReturnType, collectDataType, collectOpcs) val collectTextualBytes: Array[Byte] = textualFunc("collect", Seq(), collectPara) - + // Textual + lazy val triggerTextual: Array[Byte] = Deser.serializeArrays(Seq(initTextualBytes, depositTextualBytes, withdrawTextualBytes)) + lazy val descriptorTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeTextualBytes, createTextualBytes, recipientDepositTextualBytes, + judgeDepositTextualBytes, payerCancelTextualBytes, recipientCancelTextualBytes, judgeCancelTextualBytes, submitWorkTextualBytes, + approveWorkTextualBytes, applyToJudgeTextualBytes, judgeTextualBytes, submitPenaltyTextualBytes, + payerRefundTextualBytes, recipientRefundTextualBytes, collectTextualBytes)) } \ No newline at end of file From b5b1532db713eaf23b37d63c176bed93fe2c1f0f Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 5 Mar 2021 12:19:22 +0800 Subject: [PATCH 268/391] complete contract --- .../scala/vsys/blockchain/contract/ContractVEscrow.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 31d6c0496..f4cbfdba1 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -8,10 +8,12 @@ import vsys.utils.serialization.Deser object ContractVEscrow { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), Seq(initTrigger, depositTrigger, withdrawTrigger), // Triggers - Seq(), + Seq(supersedeFunc, createFunc, recipientDepositFunc, judgeDepositFunc, payerCancelFunc, recipientCancelFunc, + submitWorkFunc, approveWorkFunc, applyToJudgeFunc, judgeFunc, submitPenaltyFunc, + payerRefundFunc, recipientRefundFunc, collectFunc), stateVarSeq, // StateVars stateMapSeq, // StateMaps - Seq() + Seq(triggerTextual, descriptorTextual, stateVarTextual, stateMapTextual) ).explicitGet() // State Var From 4f52865b39991b68552abf9d4093d4cedf2e342c Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 8 Mar 2021 11:09:10 +0800 Subject: [PATCH 269/391] simplify the code --- .../blockchain/contract/ContractVEscrow.scala | 96 +++++++------------ 1 file changed, 36 insertions(+), 60 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index f4cbfdba1..8f4715ecf 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -77,6 +77,8 @@ object ContractVEscrow { stateMapOrderRepDepositStatus, stateMapOrderJudgeDepositStatus, stateMapOrderSubmitStatus, stateMapOrderJudgeStatus, stateMapOrderRepLockedAmount, stateMapOrderJudgeLockedAmount)) + val commonDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + // Initialization Trigger val initId: Short = 0 val initPara: Seq[String] = Seq("tokenId", "duration", "judgeDuration", @@ -136,8 +138,8 @@ object ContractVEscrow { // Create Order Function val createId: Short = 1 - val createPara: Seq[String] = Seq("recipient", "amount", "repDeposit", "judgeDeposit", "fee", "refund", "expirationTime", - "caller", "orderId", "repAmount", "needToDeposit", "totalDeposit", "repRefund", + val createPara: Seq[String] = Seq("recipient", "amount", "repDeposit", "judgeDeposit", "fee", "refund", "expirationTime") ++ + Seq("caller", "orderId", "repAmount", "needToDeposit", "totalDeposit", "repRefund", "valueTrue", "valueFalse", "amountZero") val createDataType: Array[Byte] = Array(DataType.Address.id.toByte) ++ Array.fill[Byte](5)(DataType.Amount.id.toByte) ++ @@ -201,27 +203,24 @@ object ContractVEscrow { val recipientDepositId: Short = 2 val recipientDepositPara: Seq[String] = Seq("orderId") ++ Seq("recipient", "orderStatus", "depositStatus", "valueFalse", "amount", "valueTrue") - val recipientDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) val recipientDepositOpcs: Seq[Array[Byte]] = depositCommonOpcs(false, orderRepDepositStatusMap.index, orderRecipientDepositMap.index, orderRepLockedAmountMap.index) - lazy val recipientDepositFunc: Array[Byte] = getFunctionBytes(recipientDepositId, publicFuncType, nonReturnType, recipientDepositDataType, recipientDepositOpcs) + lazy val recipientDepositFunc: Array[Byte] = getFunctionBytes(recipientDepositId, publicFuncType, nonReturnType, commonDataType, recipientDepositOpcs) val recipientDepositTextualBytes: Array[Byte] = textualFunc("recipientDeposit", Seq(), recipientDepositPara) // Judge Deposit Function val judgeDepositId: Short = 3 val judgeDepositPara: Seq[String] = Seq("orderId") ++ Seq("judge", "orderStatus", "depositStatus", "valueFalse", "amount", "valueTrue") - val judgeDepositDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) val judgeDepositOpcs: Seq[Array[Byte]] = depositCommonOpcs(true, orderJudgeDepositStatusMap.index, orderJudgeDepositMap.index, orderJudgeLockedAmountMap.index) - lazy val judgeDepositFunc: Array[Byte] = getFunctionBytes(judgeDepositId, publicFuncType, nonReturnType, judgeDepositDataType, judgeDepositOpcs) + lazy val judgeDepositFunc: Array[Byte] = getFunctionBytes(judgeDepositId, publicFuncType, nonReturnType, commonDataType, judgeDepositOpcs) val judgeDepositTextualBytes: Array[Byte] = textualFunc("judgeDeposit", Seq(), judgeDepositPara) // Order Cancel Common val cancelCommonPara: Seq[String] = Seq("orderId") ++ Seq("payer", "recipient", "judge", "orderStatus", "repDepositStatus", "judgeDepositStatus", "depositStatus", "valueFalse", "amount", "recipientAmount", "judgeAmount") - val cancelCommonDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) private def cancelCommonOpcs(callerIndex: Byte): Seq[Array[Byte]] = { Seq( cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 1.toByte), @@ -248,28 +247,38 @@ object ContractVEscrow { // Payer Cancel Function val payerCancelId: Short = 4 val payerCancelOpcs: Seq[Array[Byte]] = cancelCommonOpcs(1.toByte) - lazy val payerCancelFunc: Array[Byte] = getFunctionBytes(payerCancelId, publicFuncType, nonReturnType, cancelCommonDataType, payerCancelOpcs) + lazy val payerCancelFunc: Array[Byte] = getFunctionBytes(payerCancelId, publicFuncType, nonReturnType, commonDataType, payerCancelOpcs) val payerCancelTextualBytes: Array[Byte] = textualFunc("payerCancel", Seq(), cancelCommonPara) // Recipient Cancel Function val recipientCancelId: Short = 5 val recipientCancelOpcs: Seq[Array[Byte]] = cancelCommonOpcs(2.toByte) - lazy val recipientCancelFunc: Array[Byte] = getFunctionBytes(recipientCancelId, publicFuncType, nonReturnType, cancelCommonDataType, recipientCancelOpcs) + lazy val recipientCancelFunc: Array[Byte] = getFunctionBytes(recipientCancelId, publicFuncType, nonReturnType, commonDataType, recipientCancelOpcs) val recipientCancelTextualBytes: Array[Byte] = textualFunc("recipientCancel", Seq(), cancelCommonPara) // Judge Cancel Function val judgeCancelId: Short = 6 val judgeCancelOpcs: Seq[Array[Byte]] = cancelCommonOpcs(3.toByte) - lazy val judgeCancelFunc: Array[Byte] = getFunctionBytes(judgeCancelId, publicFuncType, nonReturnType, cancelCommonDataType, judgeCancelOpcs) + lazy val judgeCancelFunc: Array[Byte] = getFunctionBytes(judgeCancelId, publicFuncType, nonReturnType, commonDataType, judgeCancelOpcs) val judgeCancelTextualBytes: Array[Byte] = textualFunc("judgeCancel", Seq(), cancelCommonPara) + private def timestampCheck(startIndex: Int, isValid: Boolean): Seq[Array[Byte]] = { + val a: Byte = if (isValid) (startIndex + 1).toByte else startIndex.toByte + val b: Byte = if (isValid) startIndex.toByte else (startIndex + 1).toByte + Seq( + loadTimestamp ++ Array(startIndex.toByte), + cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, (startIndex + 1).toByte), + compareGreater ++ Array(a, b, (startIndex + 2).toByte), + assertTrue ++Array((startIndex + 2).toByte), + ) + } + // Submit Work Function val submitWorkId: Short = 7 val submitWorkPara: Seq[String] = Seq("orderId") ++ Seq("recipient", "orderStatus", "repDepositStatus", "judgeDepositStatus", "depositStatus", "currentTime", "expirationTime", "isValidTime", "valueFalse", "submitStatus", "duration", "time", "updateTime", "valueTrue") - val submitWorkDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) val submitWorkOpcs: Seq[Array[Byte]] = Seq( cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), assertCaller ++ Array(1.toByte), @@ -278,11 +287,7 @@ object ContractVEscrow { cdbvrMapGet ++ Array(orderRepDepositStatusMap.index, 0.toByte, 3.toByte), cdbvrMapGet ++ Array(orderJudgeDepositStatusMap.index, 0.toByte, 4.toByte), basicAnd ++ Array(3.toByte, 4.toByte, 5.toByte), - assertTrue ++ Array(5.toByte), - loadTimestamp ++ Array(6.toByte), - cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 7.toByte), - compareGreater ++ Array(7.toByte, 6.toByte, 8.toByte), - assertTrue ++Array(8.toByte), + assertTrue ++ Array(5.toByte)) ++ timestampCheck(6, true) ++ Seq( basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(9.toByte), cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 10.toByte), assertEqual ++ Array(9.toByte, 10.toByte), @@ -293,7 +298,7 @@ object ContractVEscrow { basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(14.toByte), cdbvMapSet ++ Array(orderSubmitStatusMap.index, 0.toByte, 14.toByte) ) - lazy val submitWorkFunc: Array[Byte] = getFunctionBytes(submitWorkId, publicFuncType, nonReturnType, submitWorkDataType, submitWorkOpcs) + lazy val submitWorkFunc: Array[Byte] = getFunctionBytes(submitWorkId, publicFuncType, nonReturnType, commonDataType, submitWorkOpcs) val submitWorkTextualBytes: Array[Byte] = textualFunc("submitWork", Seq(), submitWorkPara) // Approve Work Function @@ -302,18 +307,13 @@ object ContractVEscrow { Seq("payer", "orderStatus", "isSubmit", "currentTime", "expirationTime", "isValidTime", "recipient", "judge", "workAmount", "recipientLocked", "recipientAmount", "fee", "judgeLocked", "judgeAmount", "valueFalse") - val approveWorkDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) val approveWorkOpcs: Seq[Array[Byte]] = Seq( cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), assertCaller ++ Array(1.toByte), cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), assertTrue ++ Array(2.toByte), cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 3.toByte), - assertTrue ++ Array(3.toByte), - loadTimestamp ++ Array(4.toByte), - cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 5.toByte), - compareGreater ++ Array(5.toByte, 4.toByte, 6.toByte), - assertTrue ++Array(6.toByte), + assertTrue ++ Array(3.toByte)) ++ timestampCheck(4, true) ++ Seq( cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 7.toByte), cdbvrGet ++ Array(judgeStateVar.index, 0.toByte, 8.toByte), cdbvrMapGet ++ Array(orderRecipientAmountMap.index, 0.toByte, 9.toByte), @@ -321,13 +321,13 @@ object ContractVEscrow { basicAdd ++ Array(9.toByte, 10.toByte, 11.toByte), cdbvMapValAdd ++ Array(contractBalanceMap.index, 7.toByte, 11.toByte), cdbvrMapGet ++ Array(orderFeeMap.index, 0.toByte, 12.toByte), - cdbvrMapGet ++ Array(orderJudgeLockedAmountMap.index, 0.toByte, 13toByte), + cdbvrMapGet ++ Array(orderJudgeLockedAmountMap.index, 0.toByte, 13.toByte), basicAdd ++ Array(12.toByte, 13.toByte, 14.toByte), cdbvMapValAdd ++ Array(contractBalanceMap.index, 8.toByte, 14.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(15.toByte), cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 15.toByte) ) - lazy val approveWorkFunc: Array[Byte] = getFunctionBytes(approveWorkId, publicFuncType, nonReturnType, approveWorkDataType, approveWorkOpcs) + lazy val approveWorkFunc: Array[Byte] = getFunctionBytes(approveWorkId, publicFuncType, nonReturnType, commonDataType, approveWorkOpcs) val approveWorkTextualBytes: Array[Byte] = textualFunc("approveWork", Seq(), approveWorkPara) // Apply to Judge Function @@ -335,18 +335,13 @@ object ContractVEscrow { val applyToJudgePara: Seq[String] = Seq("orderId") ++ Seq("payer", "orderStatus", "isSubmit", "currentTime", "expirationTime", "isValidTime", "judgeStatus", "valueFalse", "judgeDuration", "time", "updateTime", "valueTrue") - val applyToJudgeDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) val applyToJudgeOpcs: Seq[Array[Byte]] = Seq( cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), assertCaller ++ Array(1.toByte), cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), assertTrue ++ Array(2.toByte), cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 3.toByte), - assertTrue ++ Array(3.toByte), - loadTimestamp ++ Array(4.toByte), - cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 5.toByte), - compareGreater ++ Array(5.toByte, 4.toByte, 6.toByte), - assertTrue ++ Array(6.toByte), + assertTrue ++ Array(3.toByte)) ++ timestampCheck(4, true) ++ Seq( cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 7.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(8.toByte), assertEqual ++ Array(7.toByte, 8.toByte), @@ -357,7 +352,7 @@ object ContractVEscrow { basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(12.toByte), cdbvMapSet ++ Array(orderJudgeStatusMap.index, 0.toByte, 12.toByte) ) - lazy val applyToJudgeFunc: Array[Byte] = getFunctionBytes(applyToJudgeId, publicFuncType, nonReturnType, applyToJudgeDataType, applyToJudgeOpcs) + lazy val applyToJudgeFunc: Array[Byte] = getFunctionBytes(applyToJudgeId, publicFuncType, nonReturnType, commonDataType, applyToJudgeOpcs) val applyToJudgeTextualBytes: Array[Byte] = textualFunc("applyToJudge", Seq(), applyToJudgePara) // Judge Function @@ -371,11 +366,7 @@ object ContractVEscrow { cdbvrGet ++ Array(judgeStateVar.index, 3.toByte), assertCaller ++ Array(3.toByte), cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte), - assertTrue ++ Array(4.toByte), - loadTimestamp ++ Array(5.toByte), - cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 6.toByte), - compareGreater ++ Array(6.toByte, 5.toByte, 7.toByte), - assertTrue ++ Array(7.toByte), + assertTrue ++ Array(4.toByte)) ++ timestampCheck(5, true) ++ Seq( cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 8.toByte), assertTrue ++ Array(8.toByte), cdbvrMapGet ++ Array(orderRecipientAmountMap.index, 0.toByte, 9.toByte), @@ -404,7 +395,6 @@ object ContractVEscrow { "currentTime", "expirationTime", "isExpired", "judge", "workAmount", "recipientLocked", "penaltyAmount", "fee", "judgeLocked", "judgeAmount") - val submitPenaltyDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) val submitPenaltyOpcs: Seq[Array[Byte]] = Seq( cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 1.toByte), assertCaller ++ Array(1.toByte), @@ -412,11 +402,7 @@ object ContractVEscrow { assertTrue ++ Array(2.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(3.toByte), cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 4.toByte), - assertEqual ++ Array(3.toByte, 4.toByte), - loadTimestamp ++ Array(5.toByte), - cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 6.toByte), - compareGreater ++ Array(5.toByte, 6.toByte, 7.toByte), - assertTrue ++ Array(7.toByte), + assertEqual ++ Array(3.toByte, 4.toByte)) ++ timestampCheck(5, false) ++ Seq( cdbvrGet ++ Array(judgeStateVar.index, 8.toByte), cdbvrMapGet ++ Array(orderRecipientAmountMap.index, 0.toByte, 9.toByte), cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), @@ -428,14 +414,13 @@ object ContractVEscrow { cdbvMapValAdd ++ Array(contractBalanceMap.index, 8.toByte, 14.toByte), cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 3.toByte) ) - lazy val submitPenaltyFunc: Array[Byte] = getFunctionBytes(submitPenaltyId, publicFuncType, nonReturnType, submitPenaltyDataType, submitPenaltyOpcs) + lazy val submitPenaltyFunc: Array[Byte] = getFunctionBytes(submitPenaltyId, publicFuncType, nonReturnType, commonDataType, submitPenaltyOpcs) val submitPenaltyTextualBytes: Array[Byte] = textualFunc("submitPenalty", Seq(), submitPenaltyPara) // Order Refund Common val refundCommonPara: Seq[String] = Seq("orderId") ++ Seq("payer", "recipient", "orderStatus", "judgeStatus", "currentTime", "expirationTime", "isExpired", "recipientRefund", "payerRefund", "valueFalse") - val refundCommonDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) private def refundCommonOpcs(callerIndex: Byte): Seq[Array[Byte]] = { Seq( cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 1.toByte), @@ -444,11 +429,7 @@ object ContractVEscrow { cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 3.toByte), assertTrue ++ Array(3.toByte), cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 4.toByte), - assertTrue ++ Array(4.toByte), - loadTimestamp ++ Array(5.toByte), - cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 6.toByte), - compareGreater ++ Array(5.toByte, 6.toByte, 7.toByte), - assertTrue ++ Array(7.toByte), + assertTrue ++ Array(4.toByte)) ++ timestampCheck(5, false) ++ Seq( cdbvrMapGet ++ Array(orderRecipientRefundMap.index, 0.toByte, 8.toByte), cdbvMapValAdd ++ Array(contractBalanceMap.index, 2.toByte, 8.toByte), cdbvrMapGet ++ Array(orderRefundMap.index, 0.toByte, 9.toByte), @@ -461,13 +442,13 @@ object ContractVEscrow { // Payer Refund Function val payerRefundId: Short = 12 val payerRefundOpcs: Seq[Array[Byte]] = refundCommonOpcs(1.toByte) - lazy val payerRefundFunc: Array[Byte] = getFunctionBytes(payerRefundId, publicFuncType, nonReturnType, refundCommonDataType, payerRefundOpcs) + lazy val payerRefundFunc: Array[Byte] = getFunctionBytes(payerRefundId, publicFuncType, nonReturnType, commonDataType, payerRefundOpcs) val payerRefundTextualBytes: Array[Byte] = textualFunc("payerRefund", Seq(), refundCommonPara) // Payer Refund Function val recipientRefundId: Short = 13 val recipientRefundOpcs: Seq[Array[Byte]] = refundCommonOpcs(2.toByte) - lazy val recipientRefundFunc: Array[Byte] = getFunctionBytes(recipientRefundId, publicFuncType, nonReturnType, refundCommonDataType, recipientRefundOpcs) + lazy val recipientRefundFunc: Array[Byte] = getFunctionBytes(recipientRefundId, publicFuncType, nonReturnType, commonDataType, recipientRefundOpcs) val recipientRefundTextualBytes: Array[Byte] = textualFunc("recipientRefund", Seq(), refundCommonPara) // Collect Function @@ -475,8 +456,7 @@ object ContractVEscrow { val collectPara: Seq[String] = Seq("orderId") ++ Seq("recipient", "orderStatus", "isSubmit", "valueFalse", "judgeStatus", "currentTime", "expirationTime", "isExpired", - "judge", "workAmount", "recipientLocked", "recipientAmount", "fee", "judgerLocked", "judgerAmount") - val collectDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte) + "judge", "workAmount", "recipientLocked", "recipientAmount", "fee", "judgeLocked", "judgeAmount") val collectOpcs: Seq[Array[Byte]] = Seq( cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), assertCaller ++ Array(1.toByte), @@ -486,11 +466,7 @@ object ContractVEscrow { assertCaller ++ Array(3.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(4.toByte), cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 5.toByte), - assertEqual ++ Array(4.toByte, 5.toByte), - loadTimestamp ++ Array(6.toByte), - cdbvrMapGet ++ Array(orderExpirationTimeMap.index, 0.toByte, 7.toByte), - compareGreater ++ Array(6.toByte, 7.toByte, 8.toByte), - assertTrue ++ Array(8.toByte), + assertEqual ++ Array(4.toByte, 5.toByte)) ++ timestampCheck(6, false) ++ Seq( cdbvrGet ++ Array(judgeStateVar.index, 9.toByte), cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 11.toByte), @@ -502,7 +478,7 @@ object ContractVEscrow { cdbvMapValAdd ++ Array(contractBalanceMap.index, 9.toByte, 15.toByte), cdbvMapSet ++ Array(orderStatusMap.index, 0.toByte, 4.toByte) ) - lazy val collectFunc: Array[Byte] = getFunctionBytes(collectId, publicFuncType, nonReturnType, collectDataType, collectOpcs) + lazy val collectFunc: Array[Byte] = getFunctionBytes(collectId, publicFuncType, nonReturnType, commonDataType, collectOpcs) val collectTextualBytes: Array[Byte] = textualFunc("collect", Seq(), collectPara) // Textual From 2968829e678bee39aeed939768a0117bb9021ae7 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 9 Mar 2021 12:03:18 +0800 Subject: [PATCH 270/391] fix judge func with extra para --- src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index 8f4715ecf..d140fba14 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -360,7 +360,7 @@ object ContractVEscrow { val judgePara: Seq[String] = Seq("orderId", "payerAmount", "recipientAmount") ++ Seq("judge", "orderStatus", "currentTime", "expirationTime", "isValidTime", "judgeStatus", "payToRep", "recipientLocked", "totalToPay", "totalArrange", - "fee", "judgeLocked", "judgeAmount", "valueFalse") + "payer", "recipient", "fee", "judgeLocked", "judgeAmount", "valueFalse") val judgeDataType: Array[Byte] = Array(DataType.ShortBytes.id.toByte, DataType.Amount.id.toByte, DataType.Amount.id.toByte) val judgeOpcs: Seq[Array[Byte]] = Seq( cdbvrGet ++ Array(judgeStateVar.index, 3.toByte), From 7cd9eab22d3b3059c54961ccf914ca6f86e2f782 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 11 Mar 2021 10:39:21 +0800 Subject: [PATCH 271/391] update cdbvr get or default --- .../scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala index c586639a4..495932c87 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala @@ -25,6 +25,8 @@ object CDBVROpcDiff extends OpcDiffer { Right(DataEntry(Longs.toByteArray(0L), DataType.Timestamp)) case _ if DataType(dataTypeByte) == DataType.Amount => Right(DataEntry(Longs.toByteArray(context.state.contractNumInfo(dbKey)), DataType.Amount)) + case _ if DataType(dataTypeByte) == DataType.Boolean => + Right(DataEntry(Array(0.toByte), DataType.Boolean)) case _ => Left(GenericError("Can not find the data.")) } } From 91fbfeb333dfd438d57e96792f86c8e61d7b6405 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 11 Mar 2021 10:39:57 +0800 Subject: [PATCH 272/391] add test for cdbvr get or default --- .../vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala index a557e7325..da3daff1e 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiffTest.scala @@ -54,6 +54,10 @@ class CDBVROpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven Array[Byte](0.toByte, 9.toByte, 9.toByte), DataEntry( Longs.toByteArray(1), DataType.Timestamp), Seq.empty, 0) should be ( Right(Seq(DataEntry(Longs.toByteArray(0), DataType.Timestamp)))) + CDBVROpcDiff.mapGetOrDefault(executionContext)( + Array[Byte](0.toByte, 9.toByte, 10.toByte), DataEntry( + Longs.toByteArray(1), DataType.Timestamp), Seq.empty, 0) should be ( + Right(Seq(DataEntry(Array(0.toByte), DataType.Boolean)))) CDBVROpcDiff.mapGetOrDefault(executionContext)( Array[Byte](0.toByte, 3.toByte, 3.toByte), DataEntry( Ints.toByteArray(1), DataType.Int32), Seq.empty, 0) should be ( From 05cdbe165f60a276c3efdc26f7a3d637c3ba158b Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 13:56:23 +0800 Subject: [PATCH 273/391] rewrite state check for account data entry --- src/main/scala/vsys/blockchain/contract/Contract.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index dd475eef0..2fa5f546c 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -136,13 +136,13 @@ object Contract extends ScorexLogging { stateVar.length == 2 def checkStateVar(stateVar: Array[Byte], dataType: DataType.DataTypeVal[_]): Boolean = - stateVar.length == 2 && dataType == DataType(stateVar(1)) + stateVar.length == 2 && DataType.check(dataType.id.toByte, stateVar(1)) def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.DataTypeVal[_]): Boolean = - stateMap.length == 3 && keyDataType == DataType(stateMap(1)) + stateMap.length == 3 && DataType.check(keyDataType.id.toByte, stateMap(1)) def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.DataTypeVal[_], valueDataType: DataType.DataTypeVal[_]): Boolean = - stateMap.length == 3 && keyDataType == DataType(stateMap(1)) && valueDataType == DataType(stateMap(2)) + stateMap.length == 3 && DataType.check(keyDataType.id.toByte, stateMap(1)) && DataType.check(valueDataType.id.toByte, stateMap(2)) private def isByteArrayValid(bytes: Array[Byte], textual: Seq[Array[Byte]]): Boolean = { val textualStr = textualFromBytes(textual) From aaefe44b08c4b1a7c3d82a6036f7ab980fa85276 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 13:57:39 +0800 Subject: [PATCH 274/391] fix typo --- src/main/scala/vsys/blockchain/contract/ContractPermitted.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractPermitted.scala b/src/main/scala/vsys/blockchain/contract/ContractPermitted.scala index fb3aebb16..702fc8df3 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractPermitted.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractPermitted.scala @@ -96,7 +96,7 @@ object ContractPermitted { cdbvrGet ++ Array(issuerStateVar.index, 1.toByte), assertCaller ++ Array(1.toByte), tdbSplit ++ Array(0.toByte)) - lazy val splitFunc: Array[Byte] = getFunctionBytes(splitId, publicFuncType, nonReturnType, destroyDataType, splitOpcs) + lazy val splitFunc: Array[Byte] = getFunctionBytes(splitId, publicFuncType, nonReturnType, splitDataType, splitOpcs) val splitFuncBytes: Array[Byte] = textualFunc("split", Seq(), splitPara) //send From 8943d8e217585b89a84df70de7ad2ed2c89819b3 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:00:12 +0800 Subject: [PATCH 275/391] add contract framework --- .../blockchain/contract/ContractTokenV2.scala | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala new file mode 100644 index 000000000..6b95c5b6f --- /dev/null +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -0,0 +1,24 @@ +package vsys.blockchain.contract + +import com.google.common.primitives.Ints +import vsys.blockchain.state._ +import vsys.utils.serialization.Deser + +object ContractTokenV2 { + lazy val contractTokenWhiteList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(), + Seq(), + Seq(), + Seq(), + Seq() + ).explicitGet() + + lazy val contractTokenBlackList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(), + Seq(), + Seq(), + Seq(), + Seq() + ).explicitGet() + +} From 87faf377ce94e4b9714880ae17ef3237c0fa8d3b Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:02:10 +0800 Subject: [PATCH 276/391] add state var and state map --- .../blockchain/contract/ContractTokenV2.scala | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 6b95c5b6f..ba752a2c6 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -1,6 +1,7 @@ package vsys.blockchain.contract import com.google.common.primitives.Ints +import vsys.blockchain.contract.ContractGen._ import vsys.blockchain.state._ import vsys.utils.serialization.Deser @@ -8,17 +9,27 @@ object ContractTokenV2 { lazy val contractTokenWhiteList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), Seq(), Seq(), - Seq(), - Seq(), + Seq(issuerStateVar.arr, makerStateVar.arr), + Seq(listMap.arr), Seq() ).explicitGet() lazy val contractTokenBlackList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), Seq(), Seq(), - Seq(), - Seq(), + Seq(issuerStateVar.arr, makerStateVar.arr), + Seq(listMap.arr), Seq() ).explicitGet() + // StateVar + val issuerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) + val makerStateVar: StateVar = StateVar(1.toByte, DataType.Address.id.toByte) + lazy val stateVarTextual: Array[Byte] = ContractPermitted.stateVarTextual + + // State Map + val stateMapWhitelist = List("whitelist", "userAccount", "isInList") + val stateMapBlacklist = List("blacklist", "userAccount", "isInList") + val listMap: StateMap = StateMap(0.toByte, DataType.Account.id.toByte, DataType.Boolean.id.toByte) + } From daac1ee5889881913b877378e41ac2bb157f6347 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:03:45 +0800 Subject: [PATCH 277/391] add init supersede issue and destory --- .../blockchain/contract/ContractTokenV2.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index ba752a2c6..32fbe151e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -32,4 +32,22 @@ object ContractTokenV2 { val stateMapBlacklist = List("blacklist", "userAccount", "isInList") val listMap: StateMap = StateMap(0.toByte, DataType.Account.id.toByte, DataType.Boolean.id.toByte) + // initTrigger + lazy val initFunc: Array[Byte] = ContractPermitted.initFunc + lazy val initFuncBytes: Array[Byte] = ContractPermitted.initFuncBytes + + // Functions + // Supersede + lazy val supersedeFunc: Array[Byte] = ContractPermitted.supersedeFunc + val supersedeFuncBytes: Array[Byte] = ContractPermitted.supersedeFuncBytes + + // Issue + lazy val issueFunc: Array[Byte] = ContractPermitted.issueFunc + val issueFuncBytes: Array[Byte] = ContractPermitted.issueFuncBytes + + //destroy + lazy val destroyFunc: Array[Byte] = ContractPermitted.depositFunc + val destroyFuncBytes: Array[Byte] = ContractPermitted.depositFuncBytes + + } From 9a9d320eed3a7212acbc5cdd19a2ca51dd400448 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:05:09 +0800 Subject: [PATCH 278/391] add update list func --- .../vsys/blockchain/contract/ContractTokenV2.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 32fbe151e..e3e99005a 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -49,5 +49,19 @@ object ContractTokenV2 { lazy val destroyFunc: Array[Byte] = ContractPermitted.depositFunc val destroyFuncBytes: Array[Byte] = ContractPermitted.depositFuncBytes + // Update List + val updateListId: Short = 3 + val updateListPara: Seq[String] = Seq("userAccount", + "issuer", "valueTrue") + val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val updateListOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(issuerStateVar.index, 1.toByte), + assertCaller ++ Array(1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(2.toByte), + cdbvMapSet ++ Array(listMap.index, 0.toByte, 2.toByte) + ) + lazy val updateListFunc: Array[Byte] = getFunctionBytes(updateListId, publicFuncType, nonReturnType, updateListDataType, updateListOpcs) + val updateListFuncBytes: Array[Byte] = textualFunc("updateList", Seq(), updateListPara) + } From 18b6679e2c7c8967620ef9e9ccc521bcfb9f12d9 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:06:25 +0800 Subject: [PATCH 279/391] add whilelist and blacklist check funcs --- .../blockchain/contract/ContractTokenV2.scala | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index e3e99005a..626204cb7 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -63,5 +63,28 @@ object ContractTokenV2 { lazy val updateListFunc: Array[Byte] = getFunctionBytes(updateListId, publicFuncType, nonReturnType, updateListDataType, updateListOpcs) val updateListFuncBytes: Array[Byte] = textualFunc("updateList", Seq(), updateListPara) + private def whitelistCheck(startIndex: Int, sender: Byte, recipient: Byte): Seq[Array[Byte]] = { + val isSenderInListIndex: Byte = startIndex.toByte + val isRecipientInListIndex: Byte = (startIndex + 1).toByte + Seq( + cdbvrMapGetOrDefault ++ Array(listMap.index, sender, isSenderInListIndex), + assertTrue ++ Array(isSenderInListIndex), + cdbvrMapGetOrDefault ++ Array(listMap.index, recipient, isRecipientInListIndex), + assertTrue ++ Array(isRecipientInListIndex), + ) + } + + private def blacklistCheck(startIndex: Int, sender: Byte, recipient: Byte): Seq[Array[Byte]] = { + val valueFalseIndex: Byte = startIndex.toByte + val isSenderInListIndex: Byte = (startIndex + 1).toByte + val isRecipientInListIndex: Byte = (startIndex + 2).toByte + Seq( + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(valueFalseIndex), + cdbvrMapGetOrDefault ++ Array(listMap.index, sender, isSenderInListIndex), + assertEqual ++ Array(isSenderInListIndex, valueFalseIndex), + cdbvrMapGetOrDefault ++ Array(listMap.index, recipient, isRecipientInListIndex), + assertEqual ++ Array(isRecipientInListIndex, valueFalseIndex), + ) + } } From 842d4398c426a383ea0a40ea18ee9200eb18245b Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:12:39 +0800 Subject: [PATCH 280/391] add send funcs --- .../blockchain/contract/ContractTokenV2.scala | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 626204cb7..49915b6c9 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -63,28 +63,45 @@ object ContractTokenV2 { lazy val updateListFunc: Array[Byte] = getFunctionBytes(updateListId, publicFuncType, nonReturnType, updateListDataType, updateListOpcs) val updateListFuncBytes: Array[Byte] = textualFunc("updateList", Seq(), updateListPara) - private def whitelistCheck(startIndex: Int, sender: Byte, recipient: Byte): Seq[Array[Byte]] = { - val isSenderInListIndex: Byte = startIndex.toByte - val isRecipientInListIndex: Byte = (startIndex + 1).toByte + private def whitelistCheck(sender: Byte, recipient: Byte): Seq[Array[Byte]] = Seq( - cdbvrMapGetOrDefault ++ Array(listMap.index, sender, isSenderInListIndex), - assertTrue ++ Array(isSenderInListIndex), - cdbvrMapGetOrDefault ++ Array(listMap.index, recipient, isRecipientInListIndex), - assertTrue ++ Array(isRecipientInListIndex), + cdbvrMapGetOrDefault ++ Array(listMap.index, sender, 3.toByte), + assertTrue ++ Array(3.toByte), + cdbvrMapGetOrDefault ++ Array(listMap.index, recipient, 4.toByte), + assertTrue ++ Array(4.toByte) ) - } - private def blacklistCheck(startIndex: Int, sender: Byte, recipient: Byte): Seq[Array[Byte]] = { - val valueFalseIndex: Byte = startIndex.toByte - val isSenderInListIndex: Byte = (startIndex + 1).toByte - val isRecipientInListIndex: Byte = (startIndex + 2).toByte + private def blacklistCheck(sender: Byte, recipient: Byte): Seq[Array[Byte]] = Seq( - basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(valueFalseIndex), - cdbvrMapGetOrDefault ++ Array(listMap.index, sender, isSenderInListIndex), - assertEqual ++ Array(isSenderInListIndex, valueFalseIndex), - cdbvrMapGetOrDefault ++ Array(listMap.index, recipient, isRecipientInListIndex), - assertEqual ++ Array(isRecipientInListIndex, valueFalseIndex), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(3.toByte), + cdbvrMapGetOrDefault ++ Array(listMap.index, sender, 4.toByte), + assertEqual ++ Array(4.toByte, 3.toByte), + cdbvrMapGetOrDefault ++ Array(listMap.index, recipient, 5.toByte), + assertEqual ++ Array(5.toByte, 3.toByte) ) - } + + // Send + val sendId: Short = 4 + val sendDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Amount.id.toByte) + + // Whitelist + val sendWhitelistPara: Seq[String] = Seq("recipient", "amount", + "caller", "isSenderInList", "isRecipientInList") + val sendWhitelistOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(2.toByte)) ++ whitelistCheck(2.toByte, 0.toByte) ++ Seq( + tdbaTransfer ++ Array(2.toByte, 0.toByte, 1.toByte) + ) + lazy val sendWhitelistFunc: Array[Byte] = getFunctionBytes(sendId, publicFuncType, nonReturnType, sendDataType, sendWhitelistOpcs) + val sendWhitelistFuncBytes: Array[Byte] = textualFunc("send", Seq(), sendWhitelistPara) + + // Blacklist + val sendBlacklistPara: Seq[String] = Seq("recipient", "amount", + "caller", "valueFalse", "isSenderInList", "isRecipientInList") + val sendBlacklistOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(2.toByte)) ++ blacklistCheck(2.toByte, 0.toByte) ++ Seq( + tdbaTransfer ++ Array(2.toByte, 0.toByte, 1.toByte) + ) + lazy val sendBlacklistFunc: Array[Byte] = getFunctionBytes(sendId, publicFuncType, nonReturnType, sendDataType, sendBlacklistOpcs) + val sendBlacklistFuncBytes: Array[Byte] = textualFunc("send", Seq(), sendBlacklistPara) } From b7cc946f61122a3fdc801c0bc28b3244601e71a1 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:14:36 +0800 Subject: [PATCH 281/391] add transfer func --- .../blockchain/contract/ContractTokenV2.scala | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 49915b6c9..406962229 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -104,4 +104,26 @@ object ContractTokenV2 { lazy val sendBlacklistFunc: Array[Byte] = getFunctionBytes(sendId, publicFuncType, nonReturnType, sendDataType, sendBlacklistOpcs) val sendBlacklistFuncBytes: Array[Byte] = textualFunc("send", Seq(), sendBlacklistPara) + // Transfer + val transferId: Short = 5 + val transferDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Account.id.toByte, DataType.Amount.id.toByte) + + // Whitelist + val transferWhitelistPara: Seq[String] = Seq("sender", "recipient", "amount", + "isSenderInList", "isRecipientInList") + val transferWhitelistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte)) ++ whitelistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 2.toByte)) + lazy val transferWhitelistFunc: Array[Byte] = getFunctionBytes(transferId, publicFuncType, nonReturnType, transferDataType, transferWhitelistOpcs) + val transferWhitelistFuncBytes: Array[Byte] = textualFunc("transfer", Seq(), transferWhitelistPara) + + // Blacklist + val transferBlacklistPara: Seq[String] = Seq("sender", "recipient", "amount", + "valueFalse", "isSenderInList", "isRecipientInList") + val transferBlacklistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte)) ++ blacklistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 2.toByte)) + lazy val transferBlacklistFunc: Array[Byte] = getFunctionBytes(transferId, publicFuncType, nonReturnType, transferDataType, transferBlacklistOpcs) + val transferBlacklistFuncBytes: Array[Byte] = textualFunc("transfer", Seq(), transferBlacklistPara) + } From ae4cdc2f83852b4d2a93d79ea0f336775f75a02c Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:17:47 +0800 Subject: [PATCH 282/391] add deposit and withdraw funcs --- .../blockchain/contract/ContractTokenV2.scala | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 406962229..25477486d 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -126,4 +126,49 @@ object ContractTokenV2 { lazy val transferBlacklistFunc: Array[Byte] = getFunctionBytes(transferId, publicFuncType, nonReturnType, transferDataType, transferBlacklistOpcs) val transferBlacklistFuncBytes: Array[Byte] = textualFunc("transfer", Seq(), transferBlacklistPara) + // Deposit + val depositId: Short = 6 + val depositDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.ContractAccount.id.toByte, DataType.Amount.id.toByte) + + // Whitelist + val depositWhitelistPara: Seq[String] = Seq("sender", "smart", "amount", + "isSenderInList", "isRecipientInList") + val depositWhitelistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte)) ++ whitelistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 2.toByte)) + lazy val depositWhitelistFunc: Array[Byte] = getFunctionBytes(depositId, publicFuncType, nonReturnType, depositDataType, depositWhitelistOpcs) + val depositWhitelistFuncBytes: Array[Byte] = textualFunc("deposit", Seq(), depositWhitelistPara) + + // Blacklist + val depositBlacklistPara: Seq[String] = Seq("sender", "smart", "amount", + "valueFalse", "isSenderInList", "isRecipientInList") + val depositBlacklistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte)) ++ blacklistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 2.toByte)) + lazy val depositBlacklistFunc: Array[Byte] = getFunctionBytes(depositId, publicFuncType, nonReturnType, depositDataType, depositBlacklistOpcs) + val depositBlacklistFuncBytes: Array[Byte] = textualFunc("deposit", Seq(), depositBlacklistPara) + + // Withdraw + val withdrawId: Short = 7 + val withdrawDataType: Array[Byte] = Array(DataType.ContractAccount.id.toByte, DataType.Account.id.toByte, DataType.Amount.id.toByte) + + // Whitelist + val withdrawWhitelistPara: Seq[String] = Seq("smart", "recipient", "amount", + "isSenderInList", "isRecipientInList") + val withdrawWhitelistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(1.toByte)) ++ whitelistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 2.toByte)) + lazy val withdrawWhitelistFunc: Array[Byte] = getFunctionBytes(withdrawId, publicFuncType, nonReturnType, withdrawDataType, withdrawWhitelistOpcs) + val withdrawWhitelistFuncBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawWhitelistPara) + + // Blacklist + val withdrawBlacklistPara: Seq[String] = Seq("smart", "recipient", "amount", + "valueFalse", "isSenderInList", "isRecipientInList") + val withdrawBlacklistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(1.toByte)) ++ blacklistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 2.toByte)) + lazy val withdrawBlacklistFunc: Array[Byte] = getFunctionBytes(withdrawId, publicFuncType, nonReturnType, withdrawDataType, withdrawBlacklistOpcs) + val withdrawBlacklistFuncBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawBlacklistPara) + + } From 9dc090eaee0451f53c413e4a7c0f163e1d965d0c Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:18:53 +0800 Subject: [PATCH 283/391] add read only funcs --- .../blockchain/contract/ContractTokenV2.scala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 25477486d..a553de51d 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -170,5 +170,21 @@ object ContractTokenV2 { lazy val withdrawBlacklistFunc: Array[Byte] = getFunctionBytes(withdrawId, publicFuncType, nonReturnType, withdrawDataType, withdrawBlacklistOpcs) val withdrawBlacklistFuncBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawBlacklistPara) + // TotalSupply + lazy val totalSupplyFunc: Array[Byte] = ContractPermitted.totalSupplyFunc + val totalSupplyFuncBytes: Array[Byte] = ContractPermitted.totalSupplyFuncBytes + + // MaxSupply + lazy val maxSupplyFunc: Array[Byte] = ContractPermitted.maxSupplyFunc + val maxSupplyFuncBytes: Array[Byte] = ContractPermitted.maxSupplyFuncBytes + + // BalanceOf + lazy val balanceOfFunc: Array[Byte] = ContractPermitted.balanceOfFunc + val balanceOfFuncBytes: Array[Byte] = ContractPermitted.balanceOfFuncBytes + + // GetIssuer + lazy val getIssuerFunc: Array[Byte] = ContractPermitted.getIssuerFunc + val getIssuerFuncBytes: Array[Byte] = ContractPermitted.getIssuerFuncBytes + } From 40fd57698de1f0bd0d9071b3ab7dee61a3d3e698 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 12 Mar 2021 14:23:16 +0800 Subject: [PATCH 284/391] add textual and complete the contract --- .../blockchain/contract/ContractTokenV2.scala | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index a553de51d..b9ceebf8f 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -7,19 +7,23 @@ import vsys.utils.serialization.Deser object ContractTokenV2 { lazy val contractTokenWhiteList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), - Seq(), - Seq(), + Seq(initFunc), + Seq(supersedeFunc, issueFunc, destroyFunc, updateListFunc, + sendWhitelistFunc, transferWhitelistFunc, depositWhitelistFunc, withdrawWhitelistFunc, + totalSupplyFunc, maxSupplyFunc, balanceOfFunc, getIssuerFunc), Seq(issuerStateVar.arr, makerStateVar.arr), Seq(listMap.arr), - Seq() + Seq(triggerTextual, descriptorWhitelistTextual, stateVarTextual) ).explicitGet() lazy val contractTokenBlackList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), - Seq(), - Seq(), + Seq(initFunc), + Seq(supersedeFunc, issueFunc, destroyFunc, updateListFunc, + sendBlacklistFunc, transferBlacklistFunc, depositBlacklistFunc, withdrawBlacklistFunc, + totalSupplyFunc, maxSupplyFunc, balanceOfFunc, getIssuerFunc), Seq(issuerStateVar.arr, makerStateVar.arr), Seq(listMap.arr), - Seq() + Seq(triggerTextual, descriptorBlacklistTextual, stateVarTextual) ).explicitGet() // StateVar @@ -45,7 +49,7 @@ object ContractTokenV2 { lazy val issueFunc: Array[Byte] = ContractPermitted.issueFunc val issueFuncBytes: Array[Byte] = ContractPermitted.issueFuncBytes - //destroy + // Destroy lazy val destroyFunc: Array[Byte] = ContractPermitted.depositFunc val destroyFuncBytes: Array[Byte] = ContractPermitted.depositFuncBytes @@ -186,5 +190,13 @@ object ContractTokenV2 { lazy val getIssuerFunc: Array[Byte] = ContractPermitted.getIssuerFunc val getIssuerFuncBytes: Array[Byte] = ContractPermitted.getIssuerFuncBytes + // Textual + lazy val triggerTextual: Array[Byte] = Deser.serializeArrays(Seq(initFuncBytes)) + lazy val descriptorWhitelistTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeFuncBytes, issueFuncBytes, + destroyFuncBytes, updateListFuncBytes, sendWhitelistFuncBytes, transferWhitelistFuncBytes, depositWhitelistFuncBytes, withdrawWhitelistFuncBytes, + totalSupplyFuncBytes, maxSupplyFuncBytes, balanceOfFuncBytes, getIssuerFuncBytes)) + lazy val descriptorBlacklistTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeFuncBytes, issueFuncBytes, + destroyFuncBytes, updateListFuncBytes, sendBlacklistFuncBytes, transferBlacklistFuncBytes, depositBlacklistFuncBytes, withdrawBlacklistFuncBytes, + totalSupplyFuncBytes, maxSupplyFuncBytes, balanceOfFuncBytes, getIssuerFuncBytes)) } From 20579a5b364b5115eb00ea10c1f67f31148c2153 Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 16 Mar 2021 11:07:41 +0800 Subject: [PATCH 285/391] add contract nft skeleton --- .../contract/ContractNonFungibleV2.scala | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala new file mode 100644 index 000000000..00aa61bd2 --- /dev/null +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -0,0 +1,23 @@ +package vsys.blockchain.contract + +import com.google.common.primitives.Ints +import vsys.blockchain.state._ +import vsys.utils.serialization.Deser + +object ContractNonFungibleV2 { + lazy val contractNFTWhiteList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(), + Seq(), + Seq(), + Seq(), + Seq() + ).explicitGet() + + lazy val contractNFTBlackList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + Seq(), + Seq(), + Seq(), + Seq(), + Seq() + ).explicitGet() +} From 5735b1ac4d2b8ae8bc7c9e5483f391c6a0095ee0 Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 16 Mar 2021 18:46:32 +0800 Subject: [PATCH 286/391] add state var and map --- .../blockchain/contract/ContractNonFungibleV2.scala | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index 00aa61bd2..c285f3f2b 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -1,6 +1,7 @@ package vsys.blockchain.contract import com.google.common.primitives.Ints +import vsys.blockchain.contract.ContractGen.{StateMap, StateVar} import vsys.blockchain.state._ import vsys.utils.serialization.Deser @@ -20,4 +21,16 @@ object ContractNonFungibleV2 { Seq(), Seq() ).explicitGet() + + // StateVar + val stateVarName = List("issuer", "maker") + val issuerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) + val makerStateVar: StateVar = StateVar(1.toByte, DataType.Address.id.toByte) + lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) + + // StateMap + val stateMapWhitelist = List("whitelist", "userAccount", "isInList") + val stateMapBlacklist = List("blacklist", "userAccount", "isInList") + val listMap: StateMap = StateMap(0.toByte, DataType.Account.id.toByte, DataType.Boolean.id.toByte) + } From bda61dc06739a50c0dd2f12e64e5133badef565d Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 11:07:44 +0800 Subject: [PATCH 287/391] add init supersede issue --- .../contract/ContractNonFungibleV2.scala | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index c285f3f2b..4319be773 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -1,7 +1,7 @@ package vsys.blockchain.contract -import com.google.common.primitives.Ints -import vsys.blockchain.contract.ContractGen.{StateMap, StateVar} +import com.google.common.primitives.{Ints, Longs} +import vsys.blockchain.contract.ContractGen._ import vsys.blockchain.state._ import vsys.utils.serialization.Deser @@ -33,4 +33,44 @@ object ContractNonFungibleV2 { val stateMapBlacklist = List("blacklist", "userAccount", "isInList") val listMap: StateMap = StateMap(0.toByte, DataType.Account.id.toByte, DataType.Boolean.id.toByte) + // initTrigger + val initId: Short = 0 + val initPara: Seq[String] = Seq( + "signer") + val initDataType: Array[Byte] = Array() + val initOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(0.toByte), + cdbvSet ++ Array(issuerStateVar.index, 0.toByte), + cdbvSet ++ Array(makerStateVar.index, 0.toByte)) + lazy val initFunc: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initOpcs) + lazy val initFuncBytes: Array[Byte] = textualFunc("init", Seq(), initPara) + + // Functions + // Supersede + val supersedeId: Short = 0 + val supersedePara: Seq[String] = Seq("newIssuer", + "maker") + val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val supersedeOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(makerStateVar.index, 1.toByte), + assertSigner ++ Array(1.toByte), + cdbvSet ++ Array(issuerStateVar.index, 0.toByte)) + lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) + val supersedeFuncBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) + + // Issue + val issueId: Short = 1 + val issuePara: Seq[String] = Seq("tokenDescription", + "issuer", "amount", "tokens") + val issueDataType: Array[Byte] = Array(DataType.ShortText.id.toByte) + val issueOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(issuerStateVar.index, 1.toByte), + assertCaller ++ Array(1.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(2.toByte), + tdbNewToken ++ Array(2.toByte, 2.toByte, 0.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) + } From 21b64be8fc4691567bfbb9f9060d3f37742991e0 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 15:29:33 +0800 Subject: [PATCH 288/391] add updateList --- .../contract/ContractNonFungibleV2.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index 4319be773..67a77fe58 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -73,4 +73,18 @@ object ContractNonFungibleV2 { lazy val issueFunc: Array[Byte] = getFunctionBytes(issueId, publicFuncType, nonReturnType, issueDataType, issueOpcs) val issueFuncBytes: Array[Byte] = textualFunc("issue", Seq(), issuePara) + // update list + val updateListId: Short = 2 + val updateListPara: Seq[String] = Seq("userAccount", + "issuer", "valueTrue") + val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val updateListOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(issuerStateVar.index, 1.toByte), + assertCaller ++ Array(1.toByte), + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(2.toByte), + cdbvMapSet ++ Array(listMap.index, 0.toByte, 2.toByte) + ) + lazy val updateListFunc: Array[Byte] = getFunctionBytes(updateListId, publicFuncType, nonReturnType, updateListDataType, updateListOpcs) + val updateListFuncBytes: Array[Byte] = textualFunc("updateList", Seq(), updateListPara) + } From 9b053fe9f2adce13e101ecaa9c0635e37d60c59f Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 17 Mar 2021 16:07:33 +0800 Subject: [PATCH 289/391] upgrade update list func --- .../vsys/blockchain/contract/ContractTokenV2.scala | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index b9ceebf8f..c120e301f 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -55,14 +55,13 @@ object ContractTokenV2 { // Update List val updateListId: Short = 3 - val updateListPara: Seq[String] = Seq("userAccount", - "issuer", "valueTrue") - val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val updateListPara: Seq[String] = Seq("userAccount", "value", + "issuer") + val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Boolean.id.toByte) val updateListOpcs: Seq[Array[Byte]] = Seq( - cdbvrGet ++ Array(issuerStateVar.index, 1.toByte), - assertCaller ++ Array(1.toByte), - basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(2.toByte), - cdbvMapSet ++ Array(listMap.index, 0.toByte, 2.toByte) + cdbvrGet ++ Array(issuerStateVar.index, 2.toByte), + assertCaller ++ Array(2.toByte), + cdbvMapSet ++ Array(listMap.index, 0.toByte, 1.toByte) ) lazy val updateListFunc: Array[Byte] = getFunctionBytes(updateListId, publicFuncType, nonReturnType, updateListDataType, updateListOpcs) val updateListFuncBytes: Array[Byte] = textualFunc("updateList", Seq(), updateListPara) From 8af6ff1520d03613665ff7339e46690f7f276f62 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 16:19:41 +0800 Subject: [PATCH 290/391] modify updateList --- .../blockchain/contract/ContractNonFungibleV2.scala | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index 67a77fe58..a1bc9affa 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -75,14 +75,13 @@ object ContractNonFungibleV2 { // update list val updateListId: Short = 2 - val updateListPara: Seq[String] = Seq("userAccount", - "issuer", "valueTrue") - val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val updateListPara: Seq[String] = Seq("userAccount", "value", + "issuer") + val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Boolean.id.toByte) val updateListOpcs: Seq[Array[Byte]] = Seq( - cdbvrGet ++ Array(issuerStateVar.index, 1.toByte), - assertCaller ++ Array(1.toByte), - basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(2.toByte), - cdbvMapSet ++ Array(listMap.index, 0.toByte, 2.toByte) + cdbvrGet ++ Array(issuerStateVar.index, 2.toByte), + assertCaller ++ Array(2.toByte), + cdbvMapSet ++ Array(listMap.index, 0.toByte, 1.toByte) ) lazy val updateListFunc: Array[Byte] = getFunctionBytes(updateListId, publicFuncType, nonReturnType, updateListDataType, updateListOpcs) val updateListFuncBytes: Array[Byte] = textualFunc("updateList", Seq(), updateListPara) From d5d750eacd66051134c83180cecc25caf5700908 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 16:29:02 +0800 Subject: [PATCH 291/391] add send --- .../contract/ContractNonFungibleV2.scala | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index a1bc9affa..b0ae3d824 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -6,7 +6,7 @@ import vsys.blockchain.state._ import vsys.utils.serialization.Deser object ContractNonFungibleV2 { - lazy val contractNFTWhiteList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + lazy val contractNFTWhitelist: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), Seq(), Seq(), Seq(), @@ -14,7 +14,7 @@ object ContractNonFungibleV2 { Seq() ).explicitGet() - lazy val contractNFTBlackList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), + lazy val contractNFTBlacklist: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), Seq(), Seq(), Seq(), @@ -86,4 +86,48 @@ object ContractNonFungibleV2 { lazy val updateListFunc: Array[Byte] = getFunctionBytes(updateListId, publicFuncType, nonReturnType, updateListDataType, updateListOpcs) val updateListFuncBytes: Array[Byte] = textualFunc("updateList", Seq(), updateListPara) + // send + val sendId: Short = 3 + val sendPara: Seq[String] = Seq("recipient", "tokenIndex", + "caller", "amount", "value", "isSenderInList", "isRecipientInList") + val sendDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Int32.id.toByte) + + // whitelist + val sendWhitelistOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(2.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) + ) ++ whitelistCheck(2.toByte, 0.toByte) ++ Seq( + tdbaTransfer ++ Array(2.toByte, 0.toByte, 3.toByte, 1.toByte) + ) + lazy val sendWhitelistFunc: Array[Byte] = getFunctionBytes(sendId, publicFuncType, nonReturnType, sendDataType, sendWhitelistOpcs) + val sendWhitelistFuncBytes: Array[Byte] = textualFunc("send", Seq(), sendPara) + + // blacklist + val sendBlacklistOpcs: Seq[Array[Byte]] = Seq( + loadCaller ++ Array(2.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) + ) ++ blacklistCheck(2.toByte, 0.toByte) ++ Seq( + tdbaTransfer ++ Array(2.toByte, 0.toByte, 3.toByte, 1.toByte) + ) + lazy val sendBlacklistFunc: Array[Byte] = getFunctionBytes(sendId, publicFuncType, nonReturnType, sendDataType, sendBlacklistOpcs) + val sendBlacklistFuncBytes: Array[Byte] = textualFunc("send", Seq(), sendPara) + + private def whitelistCheck(sender: Byte, recipient: Byte): Seq[Array[Byte]] = + Seq( + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(4.toByte), + cdbvrMapGetOrDefault ++ Array(listMap.index, sender, 5.toByte), + assertEqual ++ Array(5.toByte, 4.toByte), + cdbvrMapGetOrDefault ++ Array(listMap.index, recipient, 6.toByte), + assertEqual ++ Array(6.toByte, 4.toByte), + ) + + private def blacklistCheck(sender: Byte, recipient: Byte): Seq[Array[Byte]] = + Seq( + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(4.toByte), + cdbvrMapGetOrDefault ++ Array(listMap.index, sender, 5.toByte), + assertEqual ++ Array(5.toByte, 4.toByte), + cdbvrMapGetOrDefault ++ Array(listMap.index, recipient, 6.toByte), + assertEqual ++ Array(6.toByte, 4.toByte) + ) + } From dceceec628997bce2c3b3ef2402c1ef39d202a08 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 16:37:19 +0800 Subject: [PATCH 292/391] add transfer --- .../contract/ContractNonFungibleV2.scala | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index b0ae3d824..f2c3b67b0 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -112,6 +112,32 @@ object ContractNonFungibleV2 { lazy val sendBlacklistFunc: Array[Byte] = getFunctionBytes(sendId, publicFuncType, nonReturnType, sendDataType, sendBlacklistOpcs) val sendBlacklistFuncBytes: Array[Byte] = textualFunc("send", Seq(), sendPara) + // transfer + val transferId: Short = 4 + val transferPara: Seq[String] = Seq("sender", "recipient", "tokenIndex", + "amount", "value", "isSenderInList", "isRecipientInList") + val transferDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Account.id.toByte, DataType.Int32.id.toByte) + + // whitelist transfer + val transferWhitelistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) + ) ++ whitelistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) + ) + lazy val transferWhitelistFunc: Array[Byte] = getFunctionBytes(transferId, publicFuncType, nonReturnType, transferDataType, transferWhitelistOpcs) + val transferWhitelistBytes: Array[Byte] = textualFunc("transfer", Seq(), transferPara) + + // blacklist transfer + val transferBlacklistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) + ) ++ blacklistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) + ) + lazy val transferBlacklistFunc: Array[Byte] = getFunctionBytes(transferId, publicFuncType, nonReturnType, transferDataType, transferBlacklistOpcs) + val transferBlacklistBytes: Array[Byte] = textualFunc("transfer", Seq(), transferPara) + private def whitelistCheck(sender: Byte, recipient: Byte): Seq[Array[Byte]] = Seq( basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(4.toByte), From 0589102daf1f563a6dae9eeb600acb4782f51dd2 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 16:49:29 +0800 Subject: [PATCH 293/391] add deposite --- .../contract/ContractNonFungibleV2.scala | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index f2c3b67b0..8067ba2c4 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -126,7 +126,7 @@ object ContractNonFungibleV2 { tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) ) lazy val transferWhitelistFunc: Array[Byte] = getFunctionBytes(transferId, publicFuncType, nonReturnType, transferDataType, transferWhitelistOpcs) - val transferWhitelistBytes: Array[Byte] = textualFunc("transfer", Seq(), transferPara) + val transferWhitelistFuncBytes: Array[Byte] = textualFunc("transfer", Seq(), transferPara) // blacklist transfer val transferBlacklistOpcs: Seq[Array[Byte]] = Seq( @@ -136,7 +136,33 @@ object ContractNonFungibleV2 { tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) ) lazy val transferBlacklistFunc: Array[Byte] = getFunctionBytes(transferId, publicFuncType, nonReturnType, transferDataType, transferBlacklistOpcs) - val transferBlacklistBytes: Array[Byte] = textualFunc("transfer", Seq(), transferPara) + val transferBlacklistFuncBytes: Array[Byte] = textualFunc("transfer", Seq(), transferPara) + + // deposit + val depositId: Short = 4 + val depositPara: Seq[String] = Seq("sender", "smart", "tokenIndex", + "amount", "value", "isSenderInList", "isRecipientInList") + val depositDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.ContractAccount.id.toByte, DataType.Int32.id.toByte) + + // whitelist deposit + val depositWhitelistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) + ) ++ whitelistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) + ) + lazy val depositWhitelistFunc: Array[Byte] = getFunctionBytes(depositId, publicFuncType, nonReturnType, depositDataType, depositWhitelistOpcs) + val depositWhitelistFuncBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) + + // blacklist deposit + val depositBlacklistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(0.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) + ) ++ blacklistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) + ) + lazy val depositBlacklistFunc: Array[Byte] = getFunctionBytes(depositId, publicFuncType, nonReturnType, depositDataType, depositWhitelistOpcs) + val depositBlacklistFuncBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) private def whitelistCheck(sender: Byte, recipient: Byte): Seq[Array[Byte]] = Seq( From fbf5e9ce24cc56f38836998572a48d513e7b4e88 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 16:55:16 +0800 Subject: [PATCH 294/391] add withdraw --- .../contract/ContractNonFungibleV2.scala | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index 8067ba2c4..b0efd8377 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -139,7 +139,7 @@ object ContractNonFungibleV2 { val transferBlacklistFuncBytes: Array[Byte] = textualFunc("transfer", Seq(), transferPara) // deposit - val depositId: Short = 4 + val depositId: Short = 5 val depositPara: Seq[String] = Seq("sender", "smart", "tokenIndex", "amount", "value", "isSenderInList", "isRecipientInList") val depositDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.ContractAccount.id.toByte, DataType.Int32.id.toByte) @@ -161,9 +161,35 @@ object ContractNonFungibleV2 { ) ++ blacklistCheck(0.toByte, 1.toByte) ++ Seq( tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) ) - lazy val depositBlacklistFunc: Array[Byte] = getFunctionBytes(depositId, publicFuncType, nonReturnType, depositDataType, depositWhitelistOpcs) + lazy val depositBlacklistFunc: Array[Byte] = getFunctionBytes(depositId, publicFuncType, nonReturnType, depositDataType, depositBlacklistOpcs) val depositBlacklistFuncBytes: Array[Byte] = textualFunc("deposit", Seq(), depositPara) + // withdraw + val withdrawId: Short = 6 + val withdrawPara: Seq[String] = Seq("smart", "recipient", "tokenIndex", + "amount", "value", "isSenderInList", "isRecipientInList") + val withdrawDataType: Array[Byte] = Array(DataType.ContractAccount.id.toByte, DataType.Account.id.toByte, DataType.Int32.id.toByte) + + // whitelist withdraw + val withdrawWhitelistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(1.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) + ) ++ whitelistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) + ) + lazy val withdrawWhitelistFunc: Array[Byte] = getFunctionBytes(withdrawId, publicFuncType, nonReturnType, withdrawDataType, withdrawWhitelistOpcs) + val withdrawWhitelistFuncBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) + + // blacklist withdraw + val withdrawBlacklistOpcs: Seq[Array[Byte]] = Seq( + assertCaller ++ Array(1.toByte), + basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) + ) ++ whitelistCheck(0.toByte, 1.toByte) ++ Seq( + tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) + ) + lazy val withdrawBlacklistFunc: Array[Byte] = getFunctionBytes(withdrawId, publicFuncType, nonReturnType, withdrawDataType, withdrawBlacklistOpcs) + val withdrawBlacklistFuncBytes: Array[Byte] = textualFunc("withdraw", Seq(), withdrawPara) + private def whitelistCheck(sender: Byte, recipient: Byte): Seq[Array[Byte]] = Seq( basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(4.toByte), From b03fce263915dcc9c4d38834465c31a09299b0e2 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 17:03:16 +0800 Subject: [PATCH 295/391] add textual --- .../vsys/blockchain/contract/ContractNonFungibleV2.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index b0efd8377..aa6a681c6 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -208,4 +208,13 @@ object ContractNonFungibleV2 { assertEqual ++ Array(6.toByte, 4.toByte) ) + // textual + lazy val triggerTextual: Array[Byte] = Deser.serializeArrays(Seq(initFuncBytes)) + lazy val descriptorWhitelistTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeFuncBytes, issueFuncBytes, + updateListFuncBytes, sendWhitelistFuncBytes, transferWhitelistFuncBytes, + depositWhitelistFuncBytes, withdrawWhitelistFuncBytes)) + lazy val descriptorBlacklistTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeFuncBytes, issueFuncBytes, + updateListFuncBytes, sendBlacklistFuncBytes, transferBlacklistFuncBytes, + depositBlacklistFuncBytes, withdrawBlacklistFuncBytes)) + } From 05c56dbba581efab50a82beb8d7c496fc85174ac Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 17 Mar 2021 17:10:27 +0800 Subject: [PATCH 296/391] finish nft_v2 --- .../contract/ContractNonFungibleV2.scala | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index aa6a681c6..3f7b8784f 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -7,19 +7,21 @@ import vsys.utils.serialization.Deser object ContractNonFungibleV2 { lazy val contractNFTWhitelist: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), - Seq(), - Seq(), - Seq(), - Seq(), - Seq() + Seq(initFunc), + Seq(supersedeFunc, issueFunc, updateListFunc, + sendWhitelistFunc, transferWhitelistFunc, depositWhitelistFunc, withdrawWhitelistFunc), + Seq(issuerStateVar.arr, makerStateVar.arr), + Seq(listMap.arr), + Seq(triggerTextual, descriptorWhitelistTextual, stateVarTextual) ).explicitGet() lazy val contractNFTBlacklist: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), - Seq(), - Seq(), - Seq(), - Seq(), - Seq() + Seq(initFunc), + Seq(supersedeFunc, issueFunc, updateListFunc, + sendBlacklistFunc, transferBlacklistFunc, depositBlacklistFunc, withdrawBlacklistFunc), + Seq(issuerStateVar.arr, makerStateVar.arr), + Seq(listMap.arr), + Seq(triggerTextual, descriptorBlacklistTextual, stateVarTextual) ).explicitGet() // StateVar From a849c6c40dc618df2a3c12004288bb842404040d Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 17 Mar 2021 18:27:31 +0800 Subject: [PATCH 297/391] add statemap textual --- .../scala/vsys/blockchain/contract/ContractTokenV2.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index c120e301f..5d54236de 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -13,7 +13,7 @@ object ContractTokenV2 { totalSupplyFunc, maxSupplyFunc, balanceOfFunc, getIssuerFunc), Seq(issuerStateVar.arr, makerStateVar.arr), Seq(listMap.arr), - Seq(triggerTextual, descriptorWhitelistTextual, stateVarTextual) + Seq(triggerTextual, descriptorWhitelistTextual, stateVarTextual, whitelistStateMapTextual) ).explicitGet() lazy val contractTokenBlackList: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), @@ -23,7 +23,7 @@ object ContractTokenV2 { totalSupplyFunc, maxSupplyFunc, balanceOfFunc, getIssuerFunc), Seq(issuerStateVar.arr, makerStateVar.arr), Seq(listMap.arr), - Seq(triggerTextual, descriptorBlacklistTextual, stateVarTextual) + Seq(triggerTextual, descriptorBlacklistTextual, stateVarTextual, blacklistStateMapTextual) ).explicitGet() // StateVar @@ -35,6 +35,8 @@ object ContractTokenV2 { val stateMapWhitelist = List("whitelist", "userAccount", "isInList") val stateMapBlacklist = List("blacklist", "userAccount", "isInList") val listMap: StateMap = StateMap(0.toByte, DataType.Account.id.toByte, DataType.Boolean.id.toByte) + lazy val whitelistStateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapWhitelist)) + lazy val blacklistStateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapBlacklist)) // initTrigger lazy val initFunc: Array[Byte] = ContractPermitted.initFunc From 3a095d68ed71aa050ef32fa78eab9030ebcbd4bc Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 18 Mar 2021 10:56:48 +0800 Subject: [PATCH 298/391] add statemap textual --- .../vsys/blockchain/contract/ContractNonFungibleV2.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index 3f7b8784f..061c121cd 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -12,7 +12,7 @@ object ContractNonFungibleV2 { sendWhitelistFunc, transferWhitelistFunc, depositWhitelistFunc, withdrawWhitelistFunc), Seq(issuerStateVar.arr, makerStateVar.arr), Seq(listMap.arr), - Seq(triggerTextual, descriptorWhitelistTextual, stateVarTextual) + Seq(triggerTextual, descriptorWhitelistTextual, stateVarTextual, stateMapWhitelistTextual) ).explicitGet() lazy val contractNFTBlacklist: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), @@ -21,7 +21,7 @@ object ContractNonFungibleV2 { sendBlacklistFunc, transferBlacklistFunc, depositBlacklistFunc, withdrawBlacklistFunc), Seq(issuerStateVar.arr, makerStateVar.arr), Seq(listMap.arr), - Seq(triggerTextual, descriptorBlacklistTextual, stateVarTextual) + Seq(triggerTextual, descriptorBlacklistTextual, stateVarTextual, stateMapBlacklistTextual) ).explicitGet() // StateVar @@ -34,6 +34,8 @@ object ContractNonFungibleV2 { val stateMapWhitelist = List("whitelist", "userAccount", "isInList") val stateMapBlacklist = List("blacklist", "userAccount", "isInList") val listMap: StateMap = StateMap(0.toByte, DataType.Account.id.toByte, DataType.Boolean.id.toByte) + lazy val stateMapWhitelistTextual: Array[Byte] = textualStateMap(Seq(stateMapWhitelist)) + lazy val stateMapBlacklistTextual: Array[Byte] = textualStateMap(Seq(stateMapBlacklist)) // initTrigger val initId: Short = 0 From af190a14f17e8aa42f642d3d932bac948d019b02 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 22 Mar 2021 14:28:07 +0800 Subject: [PATCH 299/391] add token unittest v2 skeleton --- .../blockchain/contract/token/TokenContractV2Gen.scala | 5 +++++ .../contract/token/ExecuteTokenContractV2DiffTest.scala | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala create mode 100644 src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala new file mode 100644 index 000000000..adc511e96 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala @@ -0,0 +1,5 @@ +package vsys.blockchain.contract.token + +trait TokenContractV2Gen { + +} diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala new file mode 100644 index 000000000..d7e8f4ccf --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala @@ -0,0 +1,7 @@ +package vsys.blockchain.state.contract.token + +import org.scalatest.PropSpec + +class ExecuteTokenContractV2DiffTest extends PropSpec { + +} From 6e7d925e57a266fce05cc976a76746c58e9c30dd Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 22 Mar 2021 15:22:16 +0800 Subject: [PATCH 300/391] add datastackgen --- .../contract/token/TokenContractV2Gen.scala | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala index adc511e96..05d8d699d 100644 --- a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala @@ -1,5 +1,39 @@ package vsys.blockchain.contract.token +import com.google.common.primitives.{Ints, Longs} +import org.scalacheck.Gen +import vsys.account.Address +import vsys.blockchain.contract.{Contract, ContractTokenV2, DataEntry, DataType} + trait TokenContractV2Gen { + def initTokenV2DataStackGen(amount: Long, unity: Long, desc: String): Gen[Seq[DataEntry]] = for { + max <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) + unit <- Gen.const(DataEntry(Longs.toByteArray(unity), DataType.Amount)) + shortText <- Gen.const(DataEntry.create(desc.getBytes(), DataType.ShortText).right.get) + } yield Seq(max, unit, shortText) + + def amountDataStackGen(amount: Long): Gen[Seq[DataEntry]] = for { + res <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) + } yield Seq(res) + + def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + add <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) + } yield Seq(add) + + def sendDataStackGen(recipient: Address, amount: Long, tokenIndex: Int): Gen[Seq[DataEntry]] = for { + reci <- Gen.const(DataEntry(recipient.bytes.arr, DataType.Address)) + am <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) + index <- Gen.const(DataEntry(Ints.toByteArray(tokenIndex), DataType.Int32)) + } yield Seq(reci, am, index) + + def sendDataStackGen(recipient: Address, amount: Long): Gen[Seq[DataEntry]] = for { + reci <- Gen.const(DataEntry(recipient.bytes.arr, DataType.Address)) + am <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) + } yield Seq(reci, am) + + def tokenContractV2Gen(white: Boolean): Gen[Contract] = + if (white) ContractTokenV2.contractTokenWhiteList + else ContractTokenV2.contractTokenBlackList + } From aace8dafa6252d7e00c2bb91fc7e6a99f7523de8 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 22 Mar 2021 16:24:09 +0800 Subject: [PATCH 301/391] finish TokenContractV2Gen --- .../contract/token/TokenContractV2Gen.scala | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala index 05d8d699d..4f0e27568 100644 --- a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala @@ -1,39 +1,23 @@ package vsys.blockchain.contract.token -import com.google.common.primitives.{Ints, Longs} import org.scalacheck.Gen -import vsys.account.Address -import vsys.blockchain.contract.{Contract, ContractTokenV2, DataEntry, DataType} +import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.ContractGenHelper._ +import vsys.blockchain.contract.{Contract, ContractTokenV2, DataEntry} +import vsys.blockchain.state._ +import vsys.blockchain.transaction.contract.ExecuteContractFunctionTransaction -trait TokenContractV2Gen { +trait TokenContractV2Gen extends TokenContractGen { - def initTokenV2DataStackGen(amount: Long, unity: Long, desc: String): Gen[Seq[DataEntry]] = for { - max <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) - unit <- Gen.const(DataEntry(Longs.toByteArray(unity), DataType.Amount)) - shortText <- Gen.const(DataEntry.create(desc.getBytes(), DataType.ShortText).right.get) - } yield Seq(max, unit, shortText) - - def amountDataStackGen(amount: Long): Gen[Seq[DataEntry]] = for { - res <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) - } yield Seq(res) - - def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { - add <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) - } yield Seq(add) - - def sendDataStackGen(recipient: Address, amount: Long, tokenIndex: Int): Gen[Seq[DataEntry]] = for { - reci <- Gen.const(DataEntry(recipient.bytes.arr, DataType.Address)) - am <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) - index <- Gen.const(DataEntry(Ints.toByteArray(tokenIndex), DataType.Int32)) - } yield Seq(reci, am, index) - - def sendDataStackGen(recipient: Address, amount: Long): Gen[Seq[DataEntry]] = for { - reci <- Gen.const(DataEntry(recipient.bytes.arr, DataType.Address)) - am <- Gen.const(DataEntry(Longs.toByteArray(amount), DataType.Amount)) - } yield Seq(reci, am) + val updateListIndex: Short = 3 def tokenContractV2Gen(white: Boolean): Gen[Contract] = if (white) ContractTokenV2.contractTokenWhiteList else ContractTokenV2.contractTokenBlackList + def updateListTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, user: Address, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { + data: Seq[DataEntry] <- addressDataStackGen(user) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, updateListIndex, data, attachment, fee, feeScale, ts).explicitGet() + } From 72c93f17b7d9bbc4af78c3d2e0b4ebd907bd3599 Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 23 Mar 2021 14:29:16 +0800 Subject: [PATCH 302/391] fix typo --- src/main/scala/vsys/blockchain/contract/Contract.scala | 3 ++- src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index 2fa5f546c..461302bd2 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -151,7 +151,8 @@ object Contract extends ScorexLogging { !(bytes sameElements ContractLock.contract.bytes.arr) && !(bytes sameElements ContractNonFungible.contract.bytes.arr) && !(bytes sameElements ContractPaymentChannel.contract.bytes.arr) && - !(bytes sameElements ContractVSwap.contract.bytes.arr)) { + !(bytes sameElements ContractVSwap.contract.bytes.arr) && + !(bytes sameElements ContractTokenV2.contractTokenWhiteList.bytes.arr)) { log.warn(s"Illegal contract ${bytes.mkString(" ")}") false } else if (textualStr.isFailure || diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 5d54236de..fded0d702 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -52,8 +52,8 @@ object ContractTokenV2 { val issueFuncBytes: Array[Byte] = ContractPermitted.issueFuncBytes // Destroy - lazy val destroyFunc: Array[Byte] = ContractPermitted.depositFunc - val destroyFuncBytes: Array[Byte] = ContractPermitted.depositFuncBytes + lazy val destroyFunc: Array[Byte] = ContractPermitted.destroyFunc + val destroyFuncBytes: Array[Byte] = ContractPermitted.destroyFuncBytes // Update List val updateListId: Short = 3 From b95251875e42ff0e2e7d6b273973f721b8d34451 Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 23 Mar 2021 14:30:12 +0800 Subject: [PATCH 303/391] modify tokenContractV2Gen --- .../contract/token/TokenContractV2Gen.scala | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala index 4f0e27568..6e532ae67 100644 --- a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala @@ -3,7 +3,7 @@ package vsys.blockchain.contract.token import org.scalacheck.Gen import vsys.account.{Address, ContractAccount, PrivateKeyAccount} import vsys.blockchain.contract.ContractGenHelper._ -import vsys.blockchain.contract.{Contract, ContractTokenV2, DataEntry} +import vsys.blockchain.contract.{Contract, ContractTokenV2, DataEntry, DataType} import vsys.blockchain.state._ import vsys.blockchain.transaction.contract.ExecuteContractFunctionTransaction @@ -11,13 +11,24 @@ trait TokenContractV2Gen extends TokenContractGen { val updateListIndex: Short = 3 + def updateListDataStackGen(user: Address, value: Boolean): Gen[Seq[DataEntry]] = for { + u <- Gen.const(DataEntry(user.bytes.arr, DataType.Address)) + b: Byte = if (value) 1.toByte else 0.toByte + v <- Gen.const(DataEntry(Array(b), DataType.Boolean)) + } yield Seq(u, v) + def tokenContractV2Gen(white: Boolean): Gen[Contract] = if (white) ContractTokenV2.contractTokenWhiteList else ContractTokenV2.contractTokenBlackList - def updateListTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, user: Address, + def updateListTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, user: Address, value: Boolean, attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { - data: Seq[DataEntry] <- addressDataStackGen(user) + data: Seq[DataEntry] <- updateListDataStackGen(user, value) } yield ExecuteContractFunctionTransaction.create(signer, contractId, updateListIndex, data, attachment, fee, feeScale, ts).explicitGet() + def sendTokenGen(sender: PrivateKeyAccount, contractId: ContractAccount, rep: Address, amount: Long, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { + data: Seq[DataEntry] <- sendDataStackGen(rep, amount) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, sendIndex, data, attachment, fee, feeScale, ts).explicitGet() + } From e42e84228406ea93605d01ebc82fe2617d7f3ae7 Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 23 Mar 2021 14:36:41 +0800 Subject: [PATCH 304/391] add ex token v2 test --- .../ExecuteTokenContractV2DiffTest.scala | 101 +++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala index d7e8f4ccf..d79767644 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala @@ -1,7 +1,104 @@ package vsys.blockchain.state.contract.token -import org.scalatest.PropSpec +import cats.Monoid +import com.google.common.primitives.{Bytes, Ints, Longs} +import org.scalacheck.{Gen, Shrink} +import org.scalatest.{Matchers, PropSpec} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.{Contract, ContractGenHelper, ContractTokenV2, DataEntry, DataType} +import vsys.blockchain.contract.token.{SystemContractGen, TokenContractV2Gen} +import vsys.blockchain.state._ +import vsys.blockchain.state.diffs.assertDiffAndState +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen} +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} +import vsys.utils.serialization.Deser -class ExecuteTokenContractV2DiffTest extends PropSpec { +class ExecuteTokenContractV2DiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with SystemContractGen + with TokenContractV2Gen { + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val tokenContractV2: Gen[Contract] = tokenContractV2Gen(true) + + val preconditionsAndExecuteContractTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, Long)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + user <- accountGen + contract <- tokenContractV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisTokenGen(master, ts) + genesis2 <- genesisTokenGen(user, ts) + feeEx: Long <- smallFeeGen + descEx <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + updateList <- updateListTokenGen(master, contractId, master.toAddress, true, descEx, feeEx, ts + 1) + updateList2 <- updateListTokenGen(master, contractId, user.toAddress, true, descEx, feeEx, ts + 2) + supersede <- supersedeTokenGen(master, contractId, user.toAddress, descEx, feeEx, ts + 3) + issue <- issueTokenGen(user, contractId, 10000L, descEx, feeEx, ts + 4) + destroy <- destroyTokenGen(user, contractId, 100L, descEx, feeEx, ts + 5) + send <- sendTokenGen(user, contractId, master.toAddress, 500L, descEx, feeEx, ts + 6) + selfSend <- sendTokenGen(user, contractId, user.toAddress, 500L, descEx, feeEx, ts + 7) + } yield (genesis, genesis2, regContract, updateList, updateList2, supersede, issue, destroy, send, selfSend, send.transactionFee) + + property("execute token contract v2 function transactions doesn't break invariant") { + forAll(preconditionsAndExecuteContractTest) { case (genesis, genesis2, reg: RegisterContractTransaction, updateList, updateList2, supersede, + issue, destroy, send: ExecuteContractFunctionTransaction, selfSend, feeEx: Long) => + assertDiffAndState(Seq(TestBlock.create(Seq(genesis, genesis2)), TestBlock.create(Seq(reg, updateList, updateList2, supersede, issue, destroy))), TestBlock.create(Seq(send, selfSend))) { (blockDiff, newState) => + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -(feeEx + feeEx) + totalPortfolioDiff.effectiveBalance shouldBe -(feeEx + feeEx) + val master = reg.proofs.firstCurveProof.explicitGet().publicKey + val user = send.proofs.firstCurveProof.explicitGet().publicKey + val contractId = reg.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val issuerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) + val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(1.toByte))) + val maxKey = ByteStr(Bytes.concat(tokenId.arr, Array(0.toByte))) + val totalKey = ByteStr(Bytes.concat(tokenId.arr, Array(1.toByte))) + val unityKey = ByteStr(Bytes.concat(tokenId.arr, Array(2.toByte))) + val descKey = ByteStr(Bytes.concat(tokenId.arr, Array(3.toByte))) + val descDE = Deser.serilizeString("init") + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val userBalanceKey = ByteStr(Bytes.concat(tokenId.arr, user.toAddress.bytes.arr)) + val masterUpdateListKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(master.toAddress.bytes.arr, DataType.Address).bytes)) + val userUpdateListKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + + val (_, masterTxs) = newState.accountTransactionIds(master, 5, 0) + masterTxs.size shouldBe 5 // genesis, reg, split, supersede, send + val (_, userTxs) = newState.accountTransactionIds(user, 6, 0) + userTxs.size shouldBe 6 // genesis2, supersede, issue, destory, send, selfSend + + // contract tokens + newState.contractTokens(contractId) shouldBe 1 + + // contract info + newState.contractContent(contractId) shouldEqual Some((2, reg.id, ContractTokenV2.contractTokenWhiteList)) + newState.contractInfo(issuerKey) shouldEqual Some(DataEntry(user.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(makerKey) shouldEqual Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(masterUpdateListKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + newState.contractInfo(userUpdateListKey) shouldEqual Some(DataEntry(Array(1.toByte), DataType.Boolean)) + + // token info + newState.tokenInfo(maxKey) shouldEqual Some(DataEntry(Longs.toByteArray(100000000L), DataType.Amount)) + newState.tokenInfo(unityKey) shouldEqual Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.tokenInfo(descKey) shouldEqual Some(DataEntry.create(descDE, DataType.ShortText).explicitGet()) + newState.tokenAccountBalance(totalKey) shouldBe 10000L - 100L //destroy 100 + + // token account balance + newState.tokenAccountBalance(masterBalanceKey) shouldBe 500L // user send 500 to master + newState.tokenAccountBalance(userBalanceKey) shouldBe 10000L - 100L - 500L // send out 500 destroy 100 + } + } + } } From 349b07df7c7361228ed2028db9969088a912bcca Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 24 Mar 2021 11:40:37 +0800 Subject: [PATCH 305/391] add token contract black v2 test --- .../vsys/blockchain/contract/Contract.scala | 3 +- .../ExecuteTokenContractV2DiffTest.scala | 93 +++++++++++++++++-- 2 files changed, 87 insertions(+), 9 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index 461302bd2..3d56a0ae3 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -152,7 +152,8 @@ object Contract extends ScorexLogging { !(bytes sameElements ContractNonFungible.contract.bytes.arr) && !(bytes sameElements ContractPaymentChannel.contract.bytes.arr) && !(bytes sameElements ContractVSwap.contract.bytes.arr) && - !(bytes sameElements ContractTokenV2.contractTokenWhiteList.bytes.arr)) { + !(bytes sameElements ContractTokenV2.contractTokenWhiteList.bytes.arr) && + !(bytes sameElements ContractTokenV2.contractTokenBlackList.bytes.arr)) { log.warn(s"Illegal contract ${bytes.mkString(" ")}") false } else if (textualStr.isFailure || diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala index d79767644..78a8f9cdd 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala @@ -25,15 +25,16 @@ class ExecuteTokenContractV2DiffTest extends PropSpec private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) - val tokenContractV2: Gen[Contract] = tokenContractV2Gen(true) + val tokenContractWhiteV2: Gen[Contract] = tokenContractV2Gen(true) + val tokenContractBlackV2: Gen[Contract] = tokenContractV2Gen(false) - val preconditionsAndExecuteContractTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + val preconditionsAndExecuteContractTestWhite: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long)] = for { (master, ts, fee) <- ContractGenHelper.basicContractTestGen() user <- accountGen - contract <- tokenContractV2 + contract <- tokenContractWhiteV2 dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") description <- validDescStringGen regContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts) @@ -51,8 +52,8 @@ class ExecuteTokenContractV2DiffTest extends PropSpec selfSend <- sendTokenGen(user, contractId, user.toAddress, 500L, descEx, feeEx, ts + 7) } yield (genesis, genesis2, regContract, updateList, updateList2, supersede, issue, destroy, send, selfSend, send.transactionFee) - property("execute token contract v2 function transactions doesn't break invariant") { - forAll(preconditionsAndExecuteContractTest) { case (genesis, genesis2, reg: RegisterContractTransaction, updateList, updateList2, supersede, + property("execute token contract white v2 function transactions doesn't break invariant") { + forAll(preconditionsAndExecuteContractTestWhite) { case (genesis, genesis2, reg: RegisterContractTransaction, updateList, updateList2, supersede, issue, destroy, send: ExecuteContractFunctionTransaction, selfSend, feeEx: Long) => assertDiffAndState(Seq(TestBlock.create(Seq(genesis, genesis2)), TestBlock.create(Seq(reg, updateList, updateList2, supersede, issue, destroy))), TestBlock.create(Seq(send, selfSend))) { (blockDiff, newState) => val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) @@ -74,9 +75,9 @@ class ExecuteTokenContractV2DiffTest extends PropSpec val masterUpdateListKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(master.toAddress.bytes.arr, DataType.Address).bytes)) val userUpdateListKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) - val (_, masterTxs) = newState.accountTransactionIds(master, 5, 0) - masterTxs.size shouldBe 5 // genesis, reg, split, supersede, send - val (_, userTxs) = newState.accountTransactionIds(user, 6, 0) + val (_, masterTxs) = newState.accountTransactionIds(master, 10, 0) + masterTxs.size shouldBe 6 // genesis, reg, update, update2, supersede, send + val (_, userTxs) = newState.accountTransactionIds(user, 10, 0) userTxs.size shouldBe 6 // genesis2, supersede, issue, destory, send, selfSend // contract tokens @@ -101,4 +102,80 @@ class ExecuteTokenContractV2DiffTest extends PropSpec } } } + + val preconditionsAndExecuteContractTestBlack: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, Long)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + user <- accountGen + contract <- tokenContractBlackV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisTokenGen(master, ts) + genesis2 <- genesisTokenGen(user, ts) + feeEx: Long <- smallFeeGen + descEx <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + updateList <- updateListTokenGen(master, contractId, master.toAddress, false, descEx, feeEx, ts + 1) + updateList2 <- updateListTokenGen(master, contractId, user.toAddress, false, descEx, feeEx, ts + 2) + supersede <- supersedeTokenGen(master, contractId, user.toAddress, descEx, feeEx, ts + 3) + issue <- issueTokenGen(user, contractId, 10000L, descEx, feeEx, ts + 4) + destroy <- destroyTokenGen(user, contractId, 100L, descEx, feeEx, ts + 5) + send <- sendTokenGen(user, contractId, master.toAddress, 500L, descEx, feeEx, ts + 6) + selfSend <- sendTokenGen(user, contractId, user.toAddress, 500L, descEx, feeEx, ts + 7) + } yield (genesis, genesis2, regContract, updateList, updateList2, supersede, issue, destroy, send, selfSend, send.transactionFee) + + property("execute token contract black v2 function transactions doesn't break invariant") { + forAll(preconditionsAndExecuteContractTestBlack) { case (genesis, genesis2, reg: RegisterContractTransaction, updateList, updateList2, supersede, + issue, destroy, send: ExecuteContractFunctionTransaction, selfSend, feeEx: Long) => + assertDiffAndState(Seq(TestBlock.create(Seq(genesis, genesis2)), TestBlock.create(Seq(reg, updateList, updateList2, supersede, issue, destroy))), TestBlock.create(Seq(send, selfSend))) { (blockDiff, newState) => + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -(feeEx + feeEx) + totalPortfolioDiff.effectiveBalance shouldBe -(feeEx + feeEx) + val master = reg.proofs.firstCurveProof.explicitGet().publicKey + val user = send.proofs.firstCurveProof.explicitGet().publicKey + val contractId = reg.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val issuerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) + val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(1.toByte))) + val maxKey = ByteStr(Bytes.concat(tokenId.arr, Array(0.toByte))) + val totalKey = ByteStr(Bytes.concat(tokenId.arr, Array(1.toByte))) + val unityKey = ByteStr(Bytes.concat(tokenId.arr, Array(2.toByte))) + val descKey = ByteStr(Bytes.concat(tokenId.arr, Array(3.toByte))) + val descDE = Deser.serilizeString("init") + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val userBalanceKey = ByteStr(Bytes.concat(tokenId.arr, user.toAddress.bytes.arr)) + val masterUpdateListKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(master.toAddress.bytes.arr, DataType.Address).bytes)) + val userUpdateListKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(user.toAddress.bytes.arr, DataType.Address).bytes)) + + val (_, masterTxs) = newState.accountTransactionIds(master, 10, 0) + masterTxs.size shouldBe 6 // genesis, reg, update, update2, supersede, send + val (_, userTxs) = newState.accountTransactionIds(user, 10, 0) + userTxs.size shouldBe 6 // genesis2, supersede, issue, destory, send, selfSend + + // contract tokens + newState.contractTokens(contractId) shouldBe 1 + + // contract info + newState.contractContent(contractId) shouldEqual Some((2, reg.id, ContractTokenV2.contractTokenBlackList)) + newState.contractInfo(issuerKey) shouldEqual Some(DataEntry(user.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(makerKey) shouldEqual Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(masterUpdateListKey) shouldEqual Some(DataEntry(Array(0.toByte), DataType.Boolean)) + newState.contractInfo(userUpdateListKey) shouldEqual Some(DataEntry(Array(0.toByte), DataType.Boolean)) + + // token info + newState.tokenInfo(maxKey) shouldEqual Some(DataEntry(Longs.toByteArray(100000000L), DataType.Amount)) + newState.tokenInfo(unityKey) shouldEqual Some(DataEntry(Longs.toByteArray(100L), DataType.Amount)) + newState.tokenInfo(descKey) shouldEqual Some(DataEntry.create(descDE, DataType.ShortText).explicitGet()) + newState.tokenAccountBalance(totalKey) shouldBe 10000L - 100L //destroy 100 + + // token account balance + newState.tokenAccountBalance(masterBalanceKey) shouldBe 500L // user send 500 to master + newState.tokenAccountBalance(userBalanceKey) shouldBe 10000L - 100L - 500L // send out 500 destroy 100 + } + } + } + } From 5ffd156e512b8fda4452078553c065d45f6c03de Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 24 Mar 2021 13:44:43 +0800 Subject: [PATCH 306/391] add supersede issue destroy updateList tests --- .../ExecuteTokenContractV2DiffTest.scala | 98 ++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala index 78a8f9cdd..2e6f1fc7d 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala @@ -10,8 +10,8 @@ import vsys.blockchain.block.TestBlock import vsys.blockchain.contract.{Contract, ContractGenHelper, ContractTokenV2, DataEntry, DataType} import vsys.blockchain.contract.token.{SystemContractGen, TokenContractV2Gen} import vsys.blockchain.state._ -import vsys.blockchain.state.diffs.assertDiffAndState -import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen} +import vsys.blockchain.state.diffs.{assertDiffAndState, assertDiffEi} +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} import vsys.utils.serialization.Deser @@ -178,4 +178,98 @@ class ExecuteTokenContractV2DiffTest extends PropSpec } } + val preconditionsAndExecuteContractTransactionWhite: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + newIssuer <- accountGen + genesis <- genesisTokenGen(master, ts) + genesis1 <- genesisTokenGen(newIssuer, ts) + contract <- tokenContractWhiteV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee, ts) + contractId = regContract.contractId + description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + executeContractSupersede <- supersedeTokenGen(master, contractId, newIssuer.toAddress, description, fee, ts) + executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) + executeContractIssue1 <- issueTokenGen(newIssuer, contractId, 100000L, description, fee, ts) + executeContractDestroy <- destroyTokenGen(master, contractId, 10000L, description, fee, ts) + executeContractUpdateList <- updateListTokenGen(master, contractId, master.toAddress,true, description, fee, ts) + recipient <- mintingAddressGen + executeContractSend <- sendTokenGen(master, contractId, true, recipient, 100000L, description, fee, ts) + executeContractSelfSend <- sendTokenGen(master, contractId, true, master.toAddress, 100000L, description, fee, ts) + transferData = Seq(master.toAddress.bytes.arr, recipient.bytes.arr, Longs.toByteArray(1000L)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Amount) + executeContractTransfer <- transferTokenGen(master, contractId, true, transferData, transferType, description, fee, ts) + executeContractTotalSupply <- totalSupplyTokenGen(master, contractId, true, description, fee, ts) + executeContractMaxSupply <- maxSupplyTokenGen(master, contractId, true, description, fee, ts) + executeContractBalanceOf <- balanceOfTokenGen(master, contractId, true, master.toAddress, description, fee, ts) + executeContractGetIssuer <- getIssuerTokenGen(master, contractId, true, description, fee, ts) + } yield (genesis, genesis1, regContract, executeContractSupersede, executeContractIssue, executeContractIssue1, + executeContractDestroy, executeContractUpdateList, executeContractSend, executeContractSelfSend, + executeContractTransfer, executeContractTotalSupply, executeContractMaxSupply, executeContractBalanceOf, + executeContractGetIssuer, executeContractSelfSend.transactionFee) + + property("execute token contract white v2 transaction supersede function successfully") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, genesis1, regContract, executeContractSupersede, executeContractIssue, + executeContractIssue1, _, _, _, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.create(Seq(executeContractSupersede))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract, executeContractSupersede))), + TestBlock.createWithTxStatus(Seq(executeContractIssue), TransactionStatus.ContractInvalidCaller)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract, executeContractSupersede))), TestBlock.create(Seq(executeContractIssue1))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract white v2 transaction issue function successfully"){ + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, _, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), TestBlock.create(Seq(executeContractIssue))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract white v2 transaction destroy function successfully") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, executeContractIssue, _, + executeContractDestroy, _, _, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), TestBlock.create(Seq(executeContractDestroy))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract white v2 transaction updateList function successfully") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, _, _, _, + executeContractUpdateList, _, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), TestBlock.create(Seq(executeContractUpdateList))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + + } From 7042da3bd5c6940526ceb272ff89fcc921b8f603 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 24 Mar 2021 14:16:44 +0800 Subject: [PATCH 307/391] update tokencontractv2gen --- .../contract/token/TokenContractV2Gen.scala | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala index 6e532ae67..f947b4e8c 100644 --- a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala @@ -3,7 +3,7 @@ package vsys.blockchain.contract.token import org.scalacheck.Gen import vsys.account.{Address, ContractAccount, PrivateKeyAccount} import vsys.blockchain.contract.ContractGenHelper._ -import vsys.blockchain.contract.{Contract, ContractTokenV2, DataEntry, DataType} +import vsys.blockchain.contract.{Contract, ContractGenHelper, ContractTokenV2, DataEntry, DataType} import vsys.blockchain.state._ import vsys.blockchain.transaction.contract.ExecuteContractFunctionTransaction @@ -31,4 +31,46 @@ trait TokenContractV2Gen extends TokenContractGen { data: Seq[DataEntry] <- sendDataStackGen(rep, amount) } yield ExecuteContractFunctionTransaction.create(sender, contractId, sendIndex, data, attachment, fee, feeScale, ts).explicitGet() + def transferTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, transferIndex, data, attachment, fee, feeScale, ts).explicitGet() + } + + def depositTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, depositIndex, data, attachment, fee, feeScale, ts).explicitGet() + } + + def withdrawTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, withdrawIndex, data, attachment, fee, feeScale, ts).explicitGet() + } + + def totalSupplyTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + ExecuteContractFunctionTransaction.create(signer, contractId, totalSupplyIndex, Nil, attachment, fee, feeScale, ts).explicitGet() + } + + def maxSupplyTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + ExecuteContractFunctionTransaction.create(signer, contractId, maxSupplyIndex, Nil, attachment, fee, feeScale, ts).explicitGet() + } + + def balanceOfTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, add: Address, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + for { + data: Seq[DataEntry] <- addressDataStackGen(add) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, balanceOfIndex, data, attachment, fee, feeScale, ts).explicitGet() + } + + def getIssuerTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + ExecuteContractFunctionTransaction.create(signer, contractId, getIssuerIndex, Nil, attachment, fee, feeScale, ts).explicitGet() + } } From 11f2c2587cebd6f1fbe3f4d3b54a371c98e060a9 Mon Sep 17 00:00:00 2001 From: Icermli Date: Wed, 24 Mar 2021 14:17:54 +0800 Subject: [PATCH 308/391] add send selfsend transfer etc tests --- .../ExecuteTokenContractV2DiffTest.scala | 119 +++++++++++++++--- 1 file changed, 103 insertions(+), 16 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala index 2e6f1fc7d..a17d723dd 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala @@ -182,7 +182,8 @@ class ExecuteTokenContractV2DiffTest extends PropSpec ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, - ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, Long)] = for { + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, Long)] = for { (master, ts, fee) <- ContractGenHelper.basicContractTestGen() newIssuer <- accountGen genesis <- genesisTokenGen(master, ts) @@ -199,23 +200,24 @@ class ExecuteTokenContractV2DiffTest extends PropSpec executeContractDestroy <- destroyTokenGen(master, contractId, 10000L, description, fee, ts) executeContractUpdateList <- updateListTokenGen(master, contractId, master.toAddress,true, description, fee, ts) recipient <- mintingAddressGen - executeContractSend <- sendTokenGen(master, contractId, true, recipient, 100000L, description, fee, ts) - executeContractSelfSend <- sendTokenGen(master, contractId, true, master.toAddress, 100000L, description, fee, ts) + executeContractUpdateList2 <- updateListTokenGen(master, contractId, recipient,true, description, fee, ts) + executeContractSend <- sendTokenGen(master, contractId, recipient, 100000L, description, fee, ts) + executeContractSelfSend <- sendTokenGen(master, contractId, master.toAddress, 100000L, description, fee, ts) transferData = Seq(master.toAddress.bytes.arr, recipient.bytes.arr, Longs.toByteArray(1000L)) transferType = Seq(DataType.Address, DataType.Address, DataType.Amount) - executeContractTransfer <- transferTokenGen(master, contractId, true, transferData, transferType, description, fee, ts) - executeContractTotalSupply <- totalSupplyTokenGen(master, contractId, true, description, fee, ts) - executeContractMaxSupply <- maxSupplyTokenGen(master, contractId, true, description, fee, ts) - executeContractBalanceOf <- balanceOfTokenGen(master, contractId, true, master.toAddress, description, fee, ts) - executeContractGetIssuer <- getIssuerTokenGen(master, contractId, true, description, fee, ts) + executeContractTransfer <- transferTokenGen(master, contractId, transferData, transferType, description, fee, ts) + executeContractTotalSupply <- totalSupplyTokenGen(master, contractId, description, fee, ts) + executeContractMaxSupply <- maxSupplyTokenGen(master, contractId, description, fee, ts) + executeContractBalanceOf <- balanceOfTokenGen(master, contractId, master.toAddress, description, fee, ts) + executeContractGetIssuer <- getIssuerTokenGen(master, contractId, description, fee, ts) } yield (genesis, genesis1, regContract, executeContractSupersede, executeContractIssue, executeContractIssue1, - executeContractDestroy, executeContractUpdateList, executeContractSend, executeContractSelfSend, - executeContractTransfer, executeContractTotalSupply, executeContractMaxSupply, executeContractBalanceOf, - executeContractGetIssuer, executeContractSelfSend.transactionFee) + executeContractDestroy, executeContractUpdateList, executeContractUpdateList2, executeContractSend, + executeContractSelfSend, executeContractTransfer, executeContractTotalSupply, executeContractMaxSupply, + executeContractBalanceOf, executeContractGetIssuer, executeContractSelfSend.transactionFee) property("execute token contract white v2 transaction supersede function successfully") { forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, genesis1, regContract, executeContractSupersede, executeContractIssue, - executeContractIssue1, _, _, _, _, _, _, _, _, _, _) => + executeContractIssue1, _, _, _, _, _, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.create(Seq(executeContractSupersede))) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe false @@ -239,7 +241,7 @@ class ExecuteTokenContractV2DiffTest extends PropSpec property("execute token contract white v2 transaction issue function successfully"){ forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, - executeContractIssue, _, _, _, _, _, _, _, _, _, _, _) => + executeContractIssue, _, _, _, _, _, _, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), TestBlock.create(Seq(executeContractIssue))) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false @@ -250,7 +252,7 @@ class ExecuteTokenContractV2DiffTest extends PropSpec property("execute token contract white v2 transaction destroy function successfully") { forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, executeContractIssue, _, - executeContractDestroy, _, _, _, _, _, _, _, _, _) => + executeContractDestroy, _, _, _, _, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), TestBlock.create(Seq(executeContractDestroy))) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false @@ -261,7 +263,7 @@ class ExecuteTokenContractV2DiffTest extends PropSpec property("execute token contract white v2 transaction updateList function successfully") { forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, _, _, _, - executeContractUpdateList, _, _, _, _, _, _, _, _) => + executeContractUpdateList, _, _, _, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), TestBlock.create(Seq(executeContractUpdateList))) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe false @@ -270,6 +272,91 @@ class ExecuteTokenContractV2DiffTest extends PropSpec } } - + property("execute token contract white v2 transaction send function successfully") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, executeContractIssue, _, _, executeContractUpdateList, executeContractUpdateList2, + executeContractSend, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, executeContractUpdateList, executeContractUpdateList2))), + TestBlock.create(Seq(executeContractSend))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract white v2 transaction send function self send successfully") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract: RegisterContractTransaction, _, executeContractIssue, _, _, executeContractUpdateList, _, _, + executeContractSelfSend: ExecuteContractFunctionTransaction, _, _, _, _, _, feeSelfSend: Long) => + assertDiffAndState(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, executeContractUpdateList))), + TestBlock.create(Seq(executeContractSelfSend))) { (blockDiff, newState) => + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + val sender = executeContractSelfSend.proofs.firstCurveProof.explicitGet().publicKey + totalPortfolioDiff.balance shouldBe -feeSelfSend + totalPortfolioDiff.effectiveBalance shouldBe -feeSelfSend + val contractId = regContract.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val senderBalanceKey = ByteStr(Bytes.concat(tokenId.arr, sender.toAddress.bytes.arr)) + val (_, senderTxs) = newState.accountTransactionIds(sender.toAddress, 10, 0) + senderTxs.size shouldBe 5 // genesis and payment, issue, updateList and send + newState.tokenAccountBalance(senderBalanceKey) shouldBe 100000L + } + } + } + + property("execute token contract white v2 transaction transfer function to address successfully") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, executeContractIssue, _, _, executeContractUpdateList, + executeContractUpdateList2, _, _, executeContractTransfer, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue, executeContractUpdateList, executeContractUpdateList2))), + TestBlock.create(Seq(executeContractTransfer))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract white v2 transaction totalSupply function unsupported") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, executeContractIssue, + _, _, _, _, _, _, _, executeContractTotalSupply, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractTotalSupply), TransactionStatus.ContractUnsupportedOPC)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractUnsupportedOPC + } + } + } + + property("execute token contract white v2 transaction maxSupply function unsupported") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, executeContractIssue, + _, _, _, _, _, _, _, _, executeContractMaxSupply, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractMaxSupply), TransactionStatus.ContractUnsupportedOPC)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractUnsupportedOPC + } + } + } + + property("execute token contract white v2 transaction balanceOf function unsupported") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, executeContractIssue, + _, _, _, _, _, _, _, _, _, executeContractBalanceOf, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractBalanceOf), TransactionStatus.ContractUnsupportedOPC)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractUnsupportedOPC + } + } + } + + property("execute token contract white v2 transaction getIssuer function unsupported") { + forAll(preconditionsAndExecuteContractTransactionWhite) { case (genesis, _, regContract, _, executeContractIssue, + _, _, _, _, _, _, _, _, _, _, executeContractGetIssuer, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractGetIssuer), TransactionStatus.ContractUnsupportedOPC)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractUnsupportedOPC + } + } + } } From e47d858d5bbe034b42f04cb7c63488fbcfdd749a Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 25 Mar 2021 11:30:20 +0800 Subject: [PATCH 309/391] add black related tests --- .../ExecuteTokenContractV2DiffTest.scala | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala index a17d723dd..0a2bb2da7 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala @@ -359,4 +359,185 @@ class ExecuteTokenContractV2DiffTest extends PropSpec } } + val preconditionsAndExecuteContractTransactionBlack: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, Long)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + newIssuer <- accountGen + genesis <- genesisTokenGen(master, ts) + genesis1 <- genesisTokenGen(newIssuer, ts) + contract <- tokenContractBlackV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee, ts) + contractId = regContract.contractId + description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + executeContractSupersede <- supersedeTokenGen(master, contractId, newIssuer.toAddress, description, fee, ts) + executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) + executeContractIssue1 <- issueTokenGen(newIssuer, contractId, 100000L, description, fee, ts) + executeContractDestroy <- destroyTokenGen(master, contractId, 10000L, description, fee, ts) + executeContractUpdateList <- updateListTokenGen(master, contractId, master.toAddress,false, description, fee, ts) + recipient <- mintingAddressGen + executeContractUpdateList2 <- updateListTokenGen(master, contractId, recipient,false, description, fee, ts) + executeContractSend <- sendTokenGen(master, contractId, recipient, 100000L, description, fee, ts) + executeContractSelfSend <- sendTokenGen(master, contractId, master.toAddress, 100000L, description, fee, ts) + transferData = Seq(master.toAddress.bytes.arr, recipient.bytes.arr, Longs.toByteArray(1000L)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Amount) + executeContractTransfer <- transferTokenGen(master, contractId, transferData, transferType, description, fee, ts) + executeContractTotalSupply <- totalSupplyTokenGen(master, contractId, description, fee, ts) + executeContractMaxSupply <- maxSupplyTokenGen(master, contractId, description, fee, ts) + executeContractBalanceOf <- balanceOfTokenGen(master, contractId, master.toAddress, description, fee, ts) + executeContractGetIssuer <- getIssuerTokenGen(master, contractId, description, fee, ts) + } yield (genesis, genesis1, regContract, executeContractSupersede, executeContractIssue, executeContractIssue1, + executeContractDestroy, executeContractUpdateList, executeContractUpdateList2, executeContractSend, + executeContractSelfSend, executeContractTransfer, executeContractTotalSupply, executeContractMaxSupply, + executeContractBalanceOf, executeContractGetIssuer, executeContractSelfSend.transactionFee) + + property("execute token contract black v2 transaction supersede function successfully") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, genesis1, regContract, executeContractSupersede, executeContractIssue, + executeContractIssue1, _, _, _, _, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.create(Seq(executeContractSupersede))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract, executeContractSupersede))), + TestBlock.createWithTxStatus(Seq(executeContractIssue), TransactionStatus.ContractInvalidCaller)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract, executeContractSupersede))), TestBlock.create(Seq(executeContractIssue1))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract black v2 transaction issue function successfully"){ + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, _, _, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), TestBlock.create(Seq(executeContractIssue))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract black v2 transaction destroy function successfully") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, executeContractIssue, _, + executeContractDestroy, _, _, _, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), TestBlock.create(Seq(executeContractDestroy))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract black v2 transaction updateList function successfully") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, _, _, _, + executeContractUpdateList, _, _, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), TestBlock.create(Seq(executeContractUpdateList))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract black v2 transaction send function successfully") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, executeContractIssue, _, _, executeContractUpdateList, executeContractUpdateList2, + executeContractSend, _, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, executeContractUpdateList, executeContractUpdateList2))), + TestBlock.create(Seq(executeContractSend))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract black v2 transaction send function self send successfully") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract: RegisterContractTransaction, _, executeContractIssue, _, _, executeContractUpdateList, _, _, + executeContractSelfSend: ExecuteContractFunctionTransaction, _, _, _, _, _, feeSelfSend: Long) => + assertDiffAndState(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, executeContractUpdateList))), + TestBlock.create(Seq(executeContractSelfSend))) { (blockDiff, newState) => + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + val sender = executeContractSelfSend.proofs.firstCurveProof.explicitGet().publicKey + totalPortfolioDiff.balance shouldBe -feeSelfSend + totalPortfolioDiff.effectiveBalance shouldBe -feeSelfSend + val contractId = regContract.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val senderBalanceKey = ByteStr(Bytes.concat(tokenId.arr, sender.toAddress.bytes.arr)) + val (_, senderTxs) = newState.accountTransactionIds(sender.toAddress, 10, 0) + senderTxs.size shouldBe 5 // genesis and payment, issue, updateList and send + newState.tokenAccountBalance(senderBalanceKey) shouldBe 100000L + } + } + } + + property("execute token contract black v2 transaction transfer function to address successfully") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, executeContractIssue, _, _, executeContractUpdateList, + executeContractUpdateList2, _, _, executeContractTransfer, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue, executeContractUpdateList, executeContractUpdateList2))), + TestBlock.create(Seq(executeContractTransfer))) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe false + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("execute token contract black v2 transaction totalSupply function unsupported") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, executeContractIssue, + _, _, _, _, _, _, _, executeContractTotalSupply, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractTotalSupply), TransactionStatus.ContractUnsupportedOPC)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractUnsupportedOPC + } + } + } + + property("execute token contract black v2 transaction maxSupply function unsupported") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, executeContractIssue, + _, _, _, _, _, _, _, _, executeContractMaxSupply, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractMaxSupply), TransactionStatus.ContractUnsupportedOPC)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractUnsupportedOPC + } + } + } + + property("execute token contract black v2 transaction balanceOf function unsupported") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, executeContractIssue, + _, _, _, _, _, _, _, _, _, executeContractBalanceOf, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractBalanceOf), TransactionStatus.ContractUnsupportedOPC)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractUnsupportedOPC + } + } + } + + property("execute token contract black v2 transaction getIssuer function unsupported") { + forAll(preconditionsAndExecuteContractTransactionBlack) { case (genesis, _, regContract, _, executeContractIssue, + _, _, _, _, _, _, _, _, _, _, executeContractGetIssuer, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractGetIssuer), TransactionStatus.ContractUnsupportedOPC)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractUnsupportedOPC + } + } + } + } From e335fb59447285ca1b85af747ecc2c9c550f404b Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 25 Mar 2021 11:57:50 +0800 Subject: [PATCH 310/391] add invalid test skeleton --- ...ExecuteTokenContractV2InvalidDiffTest.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala new file mode 100644 index 000000000..e3e53016f --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala @@ -0,0 +1,18 @@ +package vsys.blockchain.state.contract.token + +import org.scalacheck.Shrink +import org.scalatest.{Matchers, PropSpec} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import vsys.blockchain.contract.token.TokenContractV2Gen +import vsys.blockchain.transaction.TransactionGen + +class ExecuteTokenContractV2InvalidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with TokenContractV2Gen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + +} From b4dfcd1078f9d9245e8dfa9039cd9976763932bf Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 25 Mar 2021 13:45:52 +0800 Subject: [PATCH 311/391] add deposit withdraw transfer tests --- ...xecuteTokenContractV2InvalidDiffTest.scala | 157 +++++++++++++++++- 1 file changed, 154 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala index e3e53016f..75c270fe9 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala @@ -1,10 +1,17 @@ package vsys.blockchain.state.contract.token -import org.scalacheck.Shrink +import com.google.common.primitives.Longs +import org.scalacheck.{Gen, Shrink} import org.scalatest.{Matchers, PropSpec} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.ContractGenHelper.feeScale +import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry, DataType} import vsys.blockchain.contract.token.TokenContractV2Gen -import vsys.blockchain.transaction.TransactionGen +import vsys.blockchain.state.EitherExt2 +import vsys.blockchain.state.diffs.assertDiffEi +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} class ExecuteTokenContractV2InvalidDiffTest extends PropSpec with PropertyChecks @@ -14,5 +21,149 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec with TokenContractV2Gen { private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) - + + val tokenContractWhiteV2: Gen[Contract] = tokenContractV2Gen(true) + + val executeTokenContractWhiteWithInvalidData: Gen[(GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contract <- tokenContractWhiteV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisTokenGen(master, ts) + rep <- mintingAddressGen + descEx <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + dataForIssueDestorySplit: Seq[DataEntry] <- amountDataStackGen(10000L) + dataForSend: Seq[DataEntry] <- sendDataStackGen(rep, 100L) + dataForSupersede: Seq[DataEntry] <- addressDataStackGen(rep) + invalidIssue: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, + contractId, issueIndex, dataForSend, descEx, fee, feeScale, ts + 1000).explicitGet() + invalidUpdateList: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, + contractId, splitIndex, dataForSupersede, descEx, fee, feeScale, ts + 1000).explicitGet() + invalidSend: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, + contractId, sendIndex, dataForSupersede, descEx, fee, feeScale, ts + 2000).explicitGet() + invalidSupersede: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, + contractId, supersedeIndex, dataForIssueDestorySplit, descEx, fee, feeScale, ts + 3000).explicitGet() + } yield (genesis, regContract, invalidIssue, invalidUpdateList, invalidSend, invalidSupersede) + + property("execute token contract white v2 transaction fail with invalid data") { + forAll(executeTokenContractWhiteWithInvalidData) { case (genesis, reg, invalid1, invalid2, invalid3, invalid4) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, reg))), TestBlock.createWithTxStatus(Seq(invalid1), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, reg))), TestBlock.createWithTxStatus(Seq(invalid2), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, reg))), TestBlock.createWithTxStatus(Seq(invalid3), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, reg))), TestBlock.createWithTxStatus(Seq(invalid4), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + + } + } + + val executeTokenContractWhiteTransferDepositWithdraw: Gen[(GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contract <- tokenContractWhiteV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisTokenGen(master, ts) + description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) + recipient <- mintingAddressGen + transferData = Seq(master.toAddress.bytes.arr, recipient.bytes.arr, Longs.toByteArray(1000L)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Amount) + transferData2 = Seq(master.toAddress.bytes.arr, contractId.bytes.arr, Longs.toByteArray(1000L)) + transferType2 = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + executeContractTransfer <- transferTokenGen(master, contractId, transferData2, transferType2, description, fee, ts) + executeContractDeposit <- depositTokenGen(master, contractId, transferData2, transferType2, description, fee, ts) + withdrawData = Seq(contractId.bytes.arr, master.toAddress.bytes.arr, Longs.toByteArray(0L)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + executeContractWithdraw <- withdrawTokenGen(master, contractId, withdrawData, withdrawType, description, fee, ts) + invalidDeposit <- depositTokenGen(master, contractId, transferData, transferType, description, fee, ts) + invalidWithdrawData = Seq(recipient.bytes.arr, master.toAddress.bytes.arr, Longs.toByteArray(1000L)) + invalidWithdrawType = Seq(DataType.Address, DataType.Address, DataType.Amount) + invalidWithdraw <- withdrawTokenGen(master, contractId, invalidWithdrawData, invalidWithdrawType, description, fee, ts) + } yield (genesis, regContract, executeContractIssue, executeContractTransfer, executeContractDeposit, executeContractWithdraw, invalidDeposit, invalidWithdraw) + + // self deposit/withdraw/transfer (self contract) + // no deposit/withdraw trigger function + property("execute token contract white v2 transaction transfer function to unsupported contract fail"){ + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, executeContractTransfer, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractTransfer), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + // no deposit/withdraw trigger function + property("execute token contract white v2 transaction deposit function to unsupported contract fail"){ + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, executeContractDeposit, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractDeposit), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + // no deposit/withdraw trigger function + property("execute token contract white v2 transaction withdraw function from unsupported contract fail"){ + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, executeContractWithdraw, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractWithdraw), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + + + property("execute token contract white v2 transaction deposit function invalid data type"){ + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, _, invalidDeposit, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidDeposit), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + } + } + + property("execute token contract white v2 transaction withdraw function invalid data type"){ + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, _, _, invalidWithdraw) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidWithdraw), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + } + } + } From fea18404b670cc181a773e39a78c69213eab3d11 Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 25 Mar 2021 14:13:59 +0800 Subject: [PATCH 312/391] add invalid white tests --- ...xecuteTokenContractV2InvalidDiffTest.scala | 80 ++++++++++++++++++- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala index 75c270fe9..fc9de80cd 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala @@ -42,7 +42,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec invalidIssue: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, contractId, issueIndex, dataForSend, descEx, fee, feeScale, ts + 1000).explicitGet() invalidUpdateList: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, - contractId, splitIndex, dataForSupersede, descEx, fee, feeScale, ts + 1000).explicitGet() + contractId, updateListIndex, dataForSupersede, descEx, fee, feeScale, ts + 1000).explicitGet() invalidSend: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, contractId, sendIndex, dataForSupersede, descEx, fee, feeScale, ts + 2000).explicitGet() invalidSupersede: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, @@ -143,8 +143,6 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } } - - property("execute token contract white v2 transaction deposit function invalid data type"){ forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, _, invalidDeposit, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), @@ -166,4 +164,80 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } } + val preconditionsAndExecuteContractTransactionInvalidWhite: Gen[(GenesisTransaction, GenesisTransaction, + RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + newIssuer <- accountGen + genesis <- genesisTokenGen(master, ts) + genesis1 <- genesisTokenGen(newIssuer, ts) + contract <- tokenContractWhiteV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee, ts) + contractId = regContract.contractId + description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + invalidSupersede <- supersedeTokenGen(newIssuer, contractId, newIssuer.toAddress, description, fee, ts) + executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) + invalidIssue <- issueTokenGen(master, contractId, 100000001L, description, fee, ts) + invalidDestroy <- destroyTokenGen(master, contractId, 100001L, description, fee, ts) + invalidUpdateList <- updateListTokenGen(newIssuer, contractId, master.toAddress,true, description, fee, ts) + recipient <- mintingAddressGen + invalidSend <- sendTokenGen(master, contractId, recipient, 1000000L, description, fee, ts) + } yield (genesis, genesis1, regContract, invalidSupersede, executeContractIssue, invalidIssue, invalidDestroy, invalidUpdateList, invalidSend) + + property("execute contract white v2 transaction invalid supersede function") { + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, genesis1, regContract, invalidSupersede, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.createWithTxStatus(Seq(invalidSupersede), TransactionStatus.ContractInvalidSigner)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidSigner + } + } + } + + property("execute contract white v2 transaction invalid issue function"){ + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, _, invalidIssue, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), + TestBlock.createWithTxStatus(Seq(invalidIssue), TransactionStatus.ContractTokenMaxExceeded)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenMaxExceeded + } // total > max + } + } + + property("execute contract white v2 transaction invalid destroy function") { + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, executeContractIssue, _, invalidDestroy, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidDestroy), TransactionStatus.ContractTokenBalanceInsufficient)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient + } + } + } + + property("execute contract white v2 transaction updateList function invalid caller") { + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, genesis1, regContract, _, _, _, _, invalidUpdateList, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.createWithTxStatus(Seq(invalidUpdateList), TransactionStatus.ContractInvalidCaller)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + } + } + + property("execute contract white v2 transaction send function failed with invalid recipient") { + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, executeContractIssue, _, _, _, invalidSend) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidSend), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + } From f6f4b6d6c9fcb6a9039a41037032574f540fe1bb Mon Sep 17 00:00:00 2001 From: Icermli Date: Thu, 25 Mar 2021 15:29:19 +0800 Subject: [PATCH 313/391] add black tests --- .../contract/token/TokenContractV2Gen.scala | 11 + ...xecuteTokenContractV2InvalidDiffTest.scala | 266 +++++++++++++++++- 2 files changed, 264 insertions(+), 13 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala index f947b4e8c..c9b09010c 100644 --- a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala @@ -17,6 +17,12 @@ trait TokenContractV2Gen extends TokenContractGen { v <- Gen.const(DataEntry(Array(b), DataType.Boolean)) } yield Seq(u, v) + def updateListDataStackGen(user: ContractAccount, value: Boolean): Gen[Seq[DataEntry]] = for { + u <- Gen.const(DataEntry(user.bytes.arr, DataType.ContractAccount)) + b: Byte = if (value) 1.toByte else 0.toByte + v <- Gen.const(DataEntry(Array(b), DataType.Boolean)) + } yield Seq(u, v) + def tokenContractV2Gen(white: Boolean): Gen[Contract] = if (white) ContractTokenV2.contractTokenWhiteList else ContractTokenV2.contractTokenBlackList @@ -26,6 +32,11 @@ trait TokenContractV2Gen extends TokenContractGen { data: Seq[DataEntry] <- updateListDataStackGen(user, value) } yield ExecuteContractFunctionTransaction.create(signer, contractId, updateListIndex, data, attachment, fee, feeScale, ts).explicitGet() + def updateListTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, user: ContractAccount, value: Boolean, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { + data: Seq[DataEntry] <- updateListDataStackGen(user, value) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, updateListIndex, data, attachment, fee, feeScale, ts).explicitGet() + def sendTokenGen(sender: PrivateKeyAccount, contractId: ContractAccount, rep: Address, amount: Long, attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { data: Seq[DataEntry] <- sendDataStackGen(rep, amount) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala index fc9de80cd..54abd34ff 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala @@ -23,6 +23,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) val tokenContractWhiteV2: Gen[Contract] = tokenContractV2Gen(true) + val tokenContractBlackV2: Gen[Contract] = tokenContractV2Gen(false) val executeTokenContractWhiteWithInvalidData: Gen[(GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, @@ -79,6 +80,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } val executeTokenContractWhiteTransferDepositWithdraw: Gen[(GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { (master, ts, fee) <- ContractGenHelper.basicContractTestGen() @@ -88,9 +90,12 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec regContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts) contractId = regContract.contractId genesis <- genesisTokenGen(master, ts) + recipient <- mintingAddressGen description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + updateList <- updateListTokenGen(master, contractId, master.toAddress,true, description, fee, ts) + updateList2 <- updateListTokenGen(master, contractId, recipient,true, description, fee, ts) + updateList3 <- updateListTokenGen(master, contractId, contractId,true, description, fee, ts) executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) - recipient <- mintingAddressGen transferData = Seq(master.toAddress.bytes.arr, recipient.bytes.arr, Longs.toByteArray(1000L)) transferType = Seq(DataType.Address, DataType.Address, DataType.Amount) transferData2 = Seq(master.toAddress.bytes.arr, contractId.bytes.arr, Longs.toByteArray(1000L)) @@ -104,13 +109,16 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec invalidWithdrawData = Seq(recipient.bytes.arr, master.toAddress.bytes.arr, Longs.toByteArray(1000L)) invalidWithdrawType = Seq(DataType.Address, DataType.Address, DataType.Amount) invalidWithdraw <- withdrawTokenGen(master, contractId, invalidWithdrawData, invalidWithdrawType, description, fee, ts) - } yield (genesis, regContract, executeContractIssue, executeContractTransfer, executeContractDeposit, executeContractWithdraw, invalidDeposit, invalidWithdraw) + } yield (genesis, regContract, executeContractIssue, executeContractTransfer, executeContractDeposit, + executeContractWithdraw, invalidDeposit, invalidWithdraw, updateList, updateList2, updateList3) // self deposit/withdraw/transfer (self contract) // no deposit/withdraw trigger function property("execute token contract white v2 transaction transfer function to unsupported contract fail"){ - forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, executeContractTransfer, _, _, _, _) => - assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, + executeContractTransfer, _, _, _, _, updateList, _, updateList3) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), + TestBlock.create(Seq(regContract, executeContractIssue, updateList, updateList3))), TestBlock.createWithTxStatus(Seq(executeContractTransfer), TransactionStatus.Failed)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true @@ -121,8 +129,10 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec // no deposit/withdraw trigger function property("execute token contract white v2 transaction deposit function to unsupported contract fail"){ - forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, executeContractDeposit, _, _, _) => - assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, + executeContractDeposit, _, _, _, updateList, _, updateList3) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), + TestBlock.create(Seq(regContract, executeContractIssue, updateList, updateList3))), TestBlock.createWithTxStatus(Seq(executeContractDeposit), TransactionStatus.Failed)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true @@ -133,8 +143,10 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec // no deposit/withdraw trigger function property("execute token contract white v2 transaction withdraw function from unsupported contract fail"){ - forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, executeContractWithdraw, _, _) => - assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, + executeContractWithdraw, _, _, updateList, _, updateList3) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), + TestBlock.create(Seq(regContract, executeContractIssue, updateList, updateList3))), TestBlock.createWithTxStatus(Seq(executeContractWithdraw), TransactionStatus.Failed)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true @@ -144,8 +156,10 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } property("execute token contract white v2 transaction deposit function invalid data type"){ - forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, _, invalidDeposit, _) => - assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, + _, invalidDeposit, _, updateList, _, updateList3) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), + TestBlock.create(Seq(regContract, executeContractIssue, updateList, updateList3))), TestBlock.createWithTxStatus(Seq(invalidDeposit), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true @@ -155,8 +169,10 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } property("execute token contract white v2 transaction withdraw function invalid data type"){ - forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, _, _, invalidWithdraw) => - assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + forAll(executeTokenContractWhiteTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, + _, _, invalidWithdraw, updateList, _, updateList3) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), + TestBlock.create(Seq(regContract, executeContractIssue, updateList, updateList3))), TestBlock.createWithTxStatus(Seq(invalidWithdraw), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch @@ -229,7 +245,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } } - property("execute contract white v2 transaction send function failed with invalid recipient") { + property("execute contract white v2 transaction send function failed with invalid sender") { forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, executeContractIssue, _, _, _, invalidSend) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), TestBlock.createWithTxStatus(Seq(invalidSend), TransactionStatus.Failed)) { blockDiffEi => @@ -240,4 +256,228 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } } + val executeTokenContractBlackWithInvalidData: Gen[(GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contract <- tokenContractBlackV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisTokenGen(master, ts) + rep <- mintingAddressGen + descEx <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + dataForIssueDestorySplit: Seq[DataEntry] <- amountDataStackGen(10000L) + dataForSend: Seq[DataEntry] <- sendDataStackGen(rep, 100L) + dataForSupersede: Seq[DataEntry] <- addressDataStackGen(rep) + invalidIssue: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, + contractId, issueIndex, dataForSend, descEx, fee, feeScale, ts + 1000).explicitGet() + invalidUpdateList: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, + contractId, updateListIndex, dataForSupersede, descEx, fee, feeScale, ts + 1000).explicitGet() + invalidSend: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, + contractId, sendIndex, dataForSupersede, descEx, fee, feeScale, ts + 2000).explicitGet() + invalidSupersede: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, + contractId, supersedeIndex, dataForIssueDestorySplit, descEx, fee, feeScale, ts + 3000).explicitGet() + } yield (genesis, regContract, invalidIssue, invalidUpdateList, invalidSend, invalidSupersede) + + property("execute token contract black v2 transaction fail with invalid data") { + forAll(executeTokenContractBlackWithInvalidData) { case (genesis, reg, invalid1, invalid2, invalid3, invalid4) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, reg))), TestBlock.createWithTxStatus(Seq(invalid1), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, reg))), TestBlock.createWithTxStatus(Seq(invalid2), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, reg))), TestBlock.createWithTxStatus(Seq(invalid3), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + + assertDiffEi(Seq(TestBlock.create(Seq(genesis, reg))), TestBlock.createWithTxStatus(Seq(invalid4), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + + } + } + + val executeTokenContractBlackTransferDepositWithdraw: Gen[(GenesisTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contract <- tokenContractBlackV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisTokenGen(master, ts) + description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) + recipient <- mintingAddressGen + transferData = Seq(master.toAddress.bytes.arr, recipient.bytes.arr, Longs.toByteArray(1000L)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Amount) + transferData2 = Seq(master.toAddress.bytes.arr, contractId.bytes.arr, Longs.toByteArray(1000L)) + transferType2 = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + executeContractTransfer <- transferTokenGen(master, contractId, transferData2, transferType2, description, fee, ts) + executeContractDeposit <- depositTokenGen(master, contractId, transferData2, transferType2, description, fee, ts) + withdrawData = Seq(contractId.bytes.arr, master.toAddress.bytes.arr, Longs.toByteArray(0L)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + executeContractWithdraw <- withdrawTokenGen(master, contractId, withdrawData, withdrawType, description, fee, ts) + invalidDeposit <- depositTokenGen(master, contractId, transferData, transferType, description, fee, ts) + invalidWithdrawData = Seq(recipient.bytes.arr, master.toAddress.bytes.arr, Longs.toByteArray(1000L)) + invalidWithdrawType = Seq(DataType.Address, DataType.Address, DataType.Amount) + invalidWithdraw <- withdrawTokenGen(master, contractId, invalidWithdrawData, invalidWithdrawType, description, fee, ts) + } yield (genesis, regContract, executeContractIssue, executeContractTransfer, executeContractDeposit, executeContractWithdraw, invalidDeposit, invalidWithdraw) + + // self deposit/withdraw/transfer (self contract) + // no deposit/withdraw trigger function + property("execute token contract black v2 transaction transfer function to unsupported contract fail"){ + forAll(executeTokenContractBlackTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, executeContractTransfer, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractTransfer), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + // no deposit/withdraw trigger function + property("execute token contract black v2 transaction deposit function to unsupported contract fail"){ + forAll(executeTokenContractBlackTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, executeContractDeposit, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractDeposit), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + // no deposit/withdraw trigger function + property("execute token contract black v2 transaction withdraw function from unsupported contract fail"){ + forAll(executeTokenContractBlackTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, executeContractWithdraw, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(executeContractWithdraw), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("execute token contract black v2 transaction deposit function invalid data type"){ + forAll(executeTokenContractBlackTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, _, invalidDeposit, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidDeposit), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + } + } + + property("execute token contract black v2 transaction withdraw function invalid data type"){ + forAll(executeTokenContractBlackTransferDepositWithdraw) { case (genesis, regContract, executeContractIssue, _, _, _, _, invalidWithdraw) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis)), TestBlock.create(Seq(regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidWithdraw), TransactionStatus.ContractDataTypeMismatch)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractDataTypeMismatch + } + } + } + + val preconditionsAndExecuteContractTransactionInvalidBlack: Gen[(GenesisTransaction, GenesisTransaction, + RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + newIssuer <- accountGen + genesis <- genesisTokenGen(master, ts) + genesis1 <- genesisTokenGen(newIssuer, ts) + contract <- tokenContractBlackV2 + dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") + description <- validDescStringGen + regContract <- registerTokenGen(master, contract, dataStack, description, fee, ts) + contractId = regContract.contractId + description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + invalidSupersede <- supersedeTokenGen(newIssuer, contractId, newIssuer.toAddress, description, fee, ts) + executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) + invalidIssue <- issueTokenGen(master, contractId, 100000001L, description, fee, ts) + invalidDestroy <- destroyTokenGen(master, contractId, 100001L, description, fee, ts) + invalidUpdateList <- updateListTokenGen(newIssuer, contractId, master.toAddress,true, description, fee, ts) + recipient <- mintingAddressGen + updateList <- updateListTokenGen(master, contractId, master.toAddress,true, description, fee, ts) + invalidSend <- sendTokenGen(master, contractId, recipient, 1000L, description, fee, ts) + } yield (genesis, genesis1, regContract, invalidSupersede, executeContractIssue, invalidIssue, invalidDestroy, + invalidUpdateList, invalidSend, updateList) + + property("execute contract black v2 transaction invalid supersede function") { + forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, genesis1, regContract, + invalidSupersede, _, _, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.createWithTxStatus(Seq(invalidSupersede), TransactionStatus.ContractInvalidSigner)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidSigner + } + } + } + + property("execute contract black v2 transaction invalid issue function"){ + forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, _, + invalidIssue, _, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), + TestBlock.createWithTxStatus(Seq(invalidIssue), TransactionStatus.ContractTokenMaxExceeded)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenMaxExceeded + } // total > max + } + } + + property("execute contract black v2 transaction invalid destroy function") { + forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, + executeContractIssue, _, invalidDestroy, _, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidDestroy), TransactionStatus.ContractTokenBalanceInsufficient)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient + } + } + } + + property("execute contract black v2 transaction updateList function invalid caller") { + forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, genesis1, regContract, _, _, _, + _, invalidUpdateList, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), + TestBlock.createWithTxStatus(Seq(invalidUpdateList), TransactionStatus.ContractInvalidCaller)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenDB.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + } + } + + property("execute contract black v2 transaction send function failed with invalid sender") { + forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, invalidSend, updateList) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, updateList))), + TestBlock.createWithTxStatus(Seq(invalidSend), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + } From 733ffd29e3339c9d27bd006061b9f21a47d8c618 Mon Sep 17 00:00:00 2001 From: Icermli Date: Fri, 26 Mar 2021 11:13:48 +0800 Subject: [PATCH 314/391] add list tests --- ...xecuteTokenContractV2InvalidDiffTest.scala | 142 ++++++++++++++++-- 1 file changed, 127 insertions(+), 15 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala index 54abd34ff..1c6e0d314 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala @@ -1,11 +1,13 @@ package vsys.blockchain.state.contract.token -import com.google.common.primitives.Longs +import com.google.common.primitives.{Ints, Longs} import org.scalacheck.{Gen, Shrink} import org.scalatest.{Matchers, PropSpec} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock import vsys.blockchain.contract.ContractGenHelper.feeScale +import vsys.blockchain.contract.lock.LockContractGen import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry, DataType} import vsys.blockchain.contract.token.TokenContractV2Gen import vsys.blockchain.state.EitherExt2 @@ -18,12 +20,14 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec with GeneratorDrivenPropertyChecks with Matchers with TransactionGen + with LockContractGen with TokenContractV2Gen { private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) val tokenContractWhiteV2: Gen[Contract] = tokenContractV2Gen(true) val tokenContractBlackV2: Gen[Contract] = tokenContractV2Gen(false) + val lockContract: Gen[Contract] = lockContractGen() val executeTokenContractWhiteWithInvalidData: Gen[(GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, @@ -183,16 +187,22 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec val preconditionsAndExecuteContractTransactionInvalidWhite: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { (master, ts, fee) <- ContractGenHelper.basicContractTestGen() newIssuer <- accountGen genesis <- genesisTokenGen(master, ts) genesis1 <- genesisTokenGen(newIssuer, ts) contract <- tokenContractWhiteV2 + contract2 <- lockContract dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") description <- validDescStringGen regContract <- registerTokenGen(master, contract, dataStack, description, fee, ts) + blackTokenId = tokenIdFromBytes(regContract.contractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + dataStack2 <- initLockContractDataStackGen(blackTokenId.arr) + regContract2 <- registerTokenGen(master, contract2, dataStack2, description, fee, ts) contractId = regContract.contractId + contractId2 = regContract2.contractId description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) invalidSupersede <- supersedeTokenGen(newIssuer, contractId, newIssuer.toAddress, description, fee, ts) executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) @@ -201,10 +211,21 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec invalidUpdateList <- updateListTokenGen(newIssuer, contractId, master.toAddress,true, description, fee, ts) recipient <- mintingAddressGen invalidSend <- sendTokenGen(master, contractId, recipient, 1000000L, description, fee, ts) - } yield (genesis, genesis1, regContract, invalidSupersede, executeContractIssue, invalidIssue, invalidDestroy, invalidUpdateList, invalidSend) + transferData = Seq(master.toAddress.bytes.arr, recipient.bytes.arr, Longs.toByteArray(1000L)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Amount) + invalidTransfer <- transferTokenGen(master, contractId, transferData, transferType, description, fee, ts) + depositData = Seq(master.toAddress.bytes.arr, contractId2.bytes.arr, Longs.toByteArray(0L)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + invalidDeposit <- depositTokenGen(master, contractId, depositData, depositType, description, fee, ts) + withdrawData = Seq(contractId2.bytes.arr, master.toAddress.bytes.arr, Longs.toByteArray(0L)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + invalidWithdraw <- withdrawTokenGen(master, contractId, withdrawData, withdrawType, description, fee, ts) + } yield (genesis, genesis1, regContract, invalidSupersede, executeContractIssue, invalidIssue, + invalidDestroy, invalidUpdateList, invalidSend, invalidTransfer, invalidDeposit, invalidWithdraw) property("execute contract white v2 transaction invalid supersede function") { - forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, genesis1, regContract, invalidSupersede, _, _, _, _, _) => + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, genesis1, regContract, + invalidSupersede, _, _, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.createWithTxStatus(Seq(invalidSupersede), TransactionStatus.ContractInvalidSigner)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true @@ -214,7 +235,8 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } property("execute contract white v2 transaction invalid issue function"){ - forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, _, invalidIssue, _, _, _) => + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, _, + invalidIssue, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), TestBlock.createWithTxStatus(Seq(invalidIssue), TransactionStatus.ContractTokenMaxExceeded)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] @@ -225,7 +247,8 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } property("execute contract white v2 transaction invalid destroy function") { - forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, executeContractIssue, _, invalidDestroy, _, _) => + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, + executeContractIssue, _, invalidDestroy, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), TestBlock.createWithTxStatus(Seq(invalidDestroy), TransactionStatus.ContractTokenBalanceInsufficient)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] @@ -236,7 +259,8 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } property("execute contract white v2 transaction updateList function invalid caller") { - forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, genesis1, regContract, _, _, _, _, invalidUpdateList, _) => + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, genesis1, regContract, _, _, + _, _, invalidUpdateList, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.createWithTxStatus(Seq(invalidUpdateList), TransactionStatus.ContractInvalidCaller)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.tokenDB.isEmpty shouldBe true @@ -245,8 +269,9 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } } - property("execute contract white v2 transaction send function failed with invalid sender") { - forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, executeContractIssue, _, _, _, invalidSend) => + property("execute contract white v2 transaction send function failed with sender not in white list") { + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, invalidSend, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), TestBlock.createWithTxStatus(Seq(invalidSend), TransactionStatus.Failed)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] @@ -256,6 +281,42 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } } + property("execute contract white v2 transaction transfer function failed with sender not in white list") { + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, _, invalidTransfer, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidTransfer), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("execute contract white v2 transaction deposit function failed with sender not in white list") { + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, _, _, invalidDeposit, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidDeposit), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("execute contract white v2 transaction withdraw function failed with sender not in white list") { + forAll(preconditionsAndExecuteContractTransactionInvalidWhite) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, _, _, _, invalidWithdraw) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), + TestBlock.createWithTxStatus(Seq(invalidWithdraw), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + val executeTokenContractBlackWithInvalidData: Gen[(GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { @@ -399,16 +460,22 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec val preconditionsAndExecuteContractTransactionInvalidBlack: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { (master, ts, fee) <- ContractGenHelper.basicContractTestGen() newIssuer <- accountGen genesis <- genesisTokenGen(master, ts) genesis1 <- genesisTokenGen(newIssuer, ts) contract <- tokenContractBlackV2 + contract2 <- lockContract dataStack: Seq[DataEntry] <- initTokenDataStackGen(100000000L, 100L, "init") description <- validDescStringGen regContract <- registerTokenGen(master, contract, dataStack, description, fee, ts) + blackTokenId = tokenIdFromBytes(regContract.contractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + dataStack2 <- initLockContractDataStackGen(blackTokenId.arr) + regContract2 <- registerTokenGen(master, contract2, dataStack2, description, fee, ts) contractId = regContract.contractId + contractId2 = regContract2.contractId description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) invalidSupersede <- supersedeTokenGen(newIssuer, contractId, newIssuer.toAddress, description, fee, ts) executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) @@ -418,12 +485,21 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec recipient <- mintingAddressGen updateList <- updateListTokenGen(master, contractId, master.toAddress,true, description, fee, ts) invalidSend <- sendTokenGen(master, contractId, recipient, 1000L, description, fee, ts) + transferData = Seq(master.toAddress.bytes.arr, recipient.bytes.arr, Longs.toByteArray(1000L)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Amount) + invalidTransfer <- transferTokenGen(master, contractId, transferData, transferType, description, fee, ts) + depositData = Seq(master.toAddress.bytes.arr, contractId2.bytes.arr, Longs.toByteArray(0L)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + invalidDeposit <- depositTokenGen(master, contractId, depositData, depositType, description, fee, ts) + withdrawData = Seq(contractId2.bytes.arr, master.toAddress.bytes.arr, Longs.toByteArray(0L)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + invalidWithdraw <- withdrawTokenGen(master, contractId, withdrawData, withdrawType, description, fee, ts) } yield (genesis, genesis1, regContract, invalidSupersede, executeContractIssue, invalidIssue, invalidDestroy, - invalidUpdateList, invalidSend, updateList) + invalidUpdateList, invalidSend, updateList, invalidTransfer, invalidDeposit, invalidWithdraw) property("execute contract black v2 transaction invalid supersede function") { forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, genesis1, regContract, - invalidSupersede, _, _, _, _, _, _) => + invalidSupersede, _, _, _, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.createWithTxStatus(Seq(invalidSupersede), TransactionStatus.ContractInvalidSigner)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true @@ -434,7 +510,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec property("execute contract black v2 transaction invalid issue function"){ forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, _, - invalidIssue, _, _, _, _) => + invalidIssue, _, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract))), TestBlock.createWithTxStatus(Seq(invalidIssue), TransactionStatus.ContractTokenMaxExceeded)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] @@ -446,7 +522,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec property("execute contract black v2 transaction invalid destroy function") { forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, - executeContractIssue, _, invalidDestroy, _, _, _) => + executeContractIssue, _, invalidDestroy, _, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue))), TestBlock.createWithTxStatus(Seq(invalidDestroy), TransactionStatus.ContractTokenBalanceInsufficient)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] @@ -458,7 +534,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec property("execute contract black v2 transaction updateList function invalid caller") { forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, genesis1, regContract, _, _, _, - _, invalidUpdateList, _, _) => + _, invalidUpdateList, _, _, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, genesis1, regContract))), TestBlock.createWithTxStatus(Seq(invalidUpdateList), TransactionStatus.ContractInvalidCaller)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] @@ -468,9 +544,9 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } } - property("execute contract black v2 transaction send function failed with invalid sender") { + property("execute contract black v2 transaction send function failed with sender in black list") { forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, - executeContractIssue, _, _, _, invalidSend, updateList) => + executeContractIssue, _, _, _, invalidSend, updateList, _, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, updateList))), TestBlock.createWithTxStatus(Seq(invalidSend), TransactionStatus.Failed)) { blockDiffEi => blockDiffEi shouldBe an[Right[_, _]] @@ -480,4 +556,40 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec } } + property("execute contract black v2 transaction transfer function failed with sender in black list") { + forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, _, updateList, invalidTransfer, _, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, updateList))), + TestBlock.createWithTxStatus(Seq(invalidTransfer), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("execute contract black v2 transaction deposit function failed with sender in black list") { + forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, _, updateList, _, invalidDeposit, _) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, updateList))), + TestBlock.createWithTxStatus(Seq(invalidDeposit), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("execute contract black v2 transaction withdraw function failed with sender in black list") { + forAll(preconditionsAndExecuteContractTransactionInvalidBlack) { case (genesis, _, regContract, _, + executeContractIssue, _, _, _, _, updateList, _, _, invalidWithdraw) => + assertDiffEi(Seq(TestBlock.create(Seq(genesis, regContract, executeContractIssue, updateList))), + TestBlock.createWithTxStatus(Seq(invalidWithdraw), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi shouldBe an[Right[_, _]] + blockDiffEi.explicitGet().txsDiff.tokenAccountBalance.isEmpty shouldBe true + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + } From 743288f7036e082b00c3e80dda2a7ed55f8dde9a Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 12 Apr 2021 12:27:55 +0800 Subject: [PATCH 315/391] update supersede func --- .../blockchain/contract/ContractTokenV2.scala | 65 ++++++++++++++----- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 5d54236de..139171350 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -10,8 +10,8 @@ object ContractTokenV2 { Seq(initFunc), Seq(supersedeFunc, issueFunc, destroyFunc, updateListFunc, sendWhitelistFunc, transferWhitelistFunc, depositWhitelistFunc, withdrawWhitelistFunc, - totalSupplyFunc, maxSupplyFunc, balanceOfFunc, getIssuerFunc), - Seq(issuerStateVar.arr, makerStateVar.arr), + totalSupplyFunc, maxSupplyFunc, balanceOfFunc, getIssuerFunc, getRegulatorFunc), + Seq(issuerStateVar.arr, makerStateVar.arr, regulatorStateVar.arr), Seq(listMap.arr), Seq(triggerTextual, descriptorWhitelistTextual, stateVarTextual, whitelistStateMapTextual) ).explicitGet() @@ -20,16 +20,18 @@ object ContractTokenV2 { Seq(initFunc), Seq(supersedeFunc, issueFunc, destroyFunc, updateListFunc, sendBlacklistFunc, transferBlacklistFunc, depositBlacklistFunc, withdrawBlacklistFunc, - totalSupplyFunc, maxSupplyFunc, balanceOfFunc, getIssuerFunc), - Seq(issuerStateVar.arr, makerStateVar.arr), + totalSupplyFunc, maxSupplyFunc, balanceOfFunc, getIssuerFunc, getRegulatorFunc), + Seq(issuerStateVar.arr, makerStateVar.arr, regulatorStateVar.arr), Seq(listMap.arr), Seq(triggerTextual, descriptorBlacklistTextual, stateVarTextual, blacklistStateMapTextual) ).explicitGet() // StateVar - val issuerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) - val makerStateVar: StateVar = StateVar(1.toByte, DataType.Address.id.toByte) - lazy val stateVarTextual: Array[Byte] = ContractPermitted.stateVarTextual + val stateVarName = List("issuer", "maker", "regulator") + val issuerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) + val makerStateVar: StateVar = StateVar(1.toByte, DataType.Address.id.toByte) + val regulatorStateVar: StateVar = StateVar(2.toByte, DataType.Address.id.toByte) + lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // State Map val stateMapWhitelist = List("whitelist", "userAccount", "isInList") @@ -39,21 +41,41 @@ object ContractTokenV2 { lazy val blacklistStateMapTextual: Array[Byte] = textualStateMap(Seq(stateMapBlacklist)) // initTrigger - lazy val initFunc: Array[Byte] = ContractPermitted.initFunc - lazy val initFuncBytes: Array[Byte] = ContractPermitted.initFuncBytes + val initId: Short = 0 + val initPara: Seq[String] = Seq("max", "unity", "tokenDescription", + "signer") + val initDataType: Array[Byte] = Array(DataType.Amount.id.toByte, DataType.Amount.id.toByte, DataType.ShortText.id.toByte) + val initOpcs: Seq[Array[Byte]] = Seq( + loadSigner ++ Array(3.toByte), + cdbvSet ++ Array(issuerStateVar.index, 3.toByte), + cdbvSet ++ Array(makerStateVar.index, 3.toByte), + cdbvSet ++ Array(regulatorStateVar.index, 3.toByte), + tdbNewToken ++ Array(0.toByte, 1.toByte, 2.toByte)) + lazy val initFunc: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initOpcs) + lazy val initFuncBytes: Array[Byte] = textualFunc("init", Seq(), initPara) // Functions // Supersede - lazy val supersedeFunc: Array[Byte] = ContractPermitted.supersedeFunc - val supersedeFuncBytes: Array[Byte] = ContractPermitted.supersedeFuncBytes + val supersedeId: Short = 0 + val supersedeIdWithoutSplit: Short = 0 + val supersedePara: Seq[String] = Seq("newIssuer", "newRegulator", + "maker") + val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Account.id.toByte) + val supersedeOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(makerStateVar.index, 2.toByte), + assertSigner ++ Array(2.toByte), + cdbvSet ++ Array(issuerStateVar.index, 0.toByte), + cdbvSet ++ Array(regulatorStateVar.index, 1.toByte)) + lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) + val supersedeFuncBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) // Issue lazy val issueFunc: Array[Byte] = ContractPermitted.issueFunc val issueFuncBytes: Array[Byte] = ContractPermitted.issueFuncBytes // Destroy - lazy val destroyFunc: Array[Byte] = ContractPermitted.depositFunc - val destroyFuncBytes: Array[Byte] = ContractPermitted.depositFuncBytes + lazy val destroyFunc: Array[Byte] = ContractPermitted.destroyFunc + val destroyFuncBytes: Array[Byte] = ContractPermitted.destroyFuncBytes // Update List val updateListId: Short = 3 @@ -61,7 +83,7 @@ object ContractTokenV2 { "issuer") val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Boolean.id.toByte) val updateListOpcs: Seq[Array[Byte]] = Seq( - cdbvrGet ++ Array(issuerStateVar.index, 2.toByte), + cdbvrGet ++ Array(regulatorStateVar.index, 2.toByte), assertCaller ++ Array(2.toByte), cdbvMapSet ++ Array(listMap.index, 0.toByte, 1.toByte) ) @@ -191,13 +213,24 @@ object ContractTokenV2 { lazy val getIssuerFunc: Array[Byte] = ContractPermitted.getIssuerFunc val getIssuerFuncBytes: Array[Byte] = ContractPermitted.getIssuerFuncBytes + // GetRegulator + val getRegulatorId: Short = 12 + val getRegulatorPara: Seq[String] = Seq( + "regulator") + val getRegulatorDataType: Array[Byte] = Array() + val getRegulatorOpcs: Seq[Array[Byte]] = Seq( + cdbvrGet ++ Array(regulatorStateVar.index, 0.toByte), + returnValue ++ Array(0.toByte)) + lazy val getRegulatorFunc: Array[Byte] = getFunctionBytes(getRegulatorId, publicFuncType, Array(DataType.Account.id.toByte), getRegulatorDataType, getRegulatorOpcs) + val getRegulatorFuncBytes: Array[Byte] = textualFunc("getRegulator", Seq("regulator"), getRegulatorPara) + // Textual lazy val triggerTextual: Array[Byte] = Deser.serializeArrays(Seq(initFuncBytes)) lazy val descriptorWhitelistTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeFuncBytes, issueFuncBytes, destroyFuncBytes, updateListFuncBytes, sendWhitelistFuncBytes, transferWhitelistFuncBytes, depositWhitelistFuncBytes, withdrawWhitelistFuncBytes, - totalSupplyFuncBytes, maxSupplyFuncBytes, balanceOfFuncBytes, getIssuerFuncBytes)) + totalSupplyFuncBytes, maxSupplyFuncBytes, balanceOfFuncBytes, getIssuerFuncBytes, getRegulatorFuncBytes)) lazy val descriptorBlacklistTextual: Array[Byte] = Deser.serializeArrays(Seq(supersedeFuncBytes, issueFuncBytes, destroyFuncBytes, updateListFuncBytes, sendBlacklistFuncBytes, transferBlacklistFuncBytes, depositBlacklistFuncBytes, withdrawBlacklistFuncBytes, - totalSupplyFuncBytes, maxSupplyFuncBytes, balanceOfFuncBytes, getIssuerFuncBytes)) + totalSupplyFuncBytes, maxSupplyFuncBytes, balanceOfFuncBytes, getIssuerFuncBytes, getRegulatorFuncBytes)) } From 75521dceec53d31dc5141c9a178b02ec69cafed3 Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 12 Apr 2021 13:47:39 +0800 Subject: [PATCH 316/391] update textual name --- src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala index 139171350..206133487 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractTokenV2.scala @@ -80,7 +80,7 @@ object ContractTokenV2 { // Update List val updateListId: Short = 3 val updateListPara: Seq[String] = Seq("userAccount", "value", - "issuer") + "regulator") val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Boolean.id.toByte) val updateListOpcs: Seq[Array[Byte]] = Seq( cdbvrGet ++ Array(regulatorStateVar.index, 2.toByte), From 3f64c582cd445165072692bca836c2400d6cba25 Mon Sep 17 00:00:00 2001 From: Icermli Date: Mon, 12 Apr 2021 14:05:42 +0800 Subject: [PATCH 317/391] update supersede func --- .../contract/ContractNonFungibleV2.scala | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index 061c121cd..b7cb97d1e 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -10,7 +10,7 @@ object ContractNonFungibleV2 { Seq(initFunc), Seq(supersedeFunc, issueFunc, updateListFunc, sendWhitelistFunc, transferWhitelistFunc, depositWhitelistFunc, withdrawWhitelistFunc), - Seq(issuerStateVar.arr, makerStateVar.arr), + Seq(issuerStateVar.arr, makerStateVar.arr, regulatorStateVar.arr), Seq(listMap.arr), Seq(triggerTextual, descriptorWhitelistTextual, stateVarTextual, stateMapWhitelistTextual) ).explicitGet() @@ -19,15 +19,16 @@ object ContractNonFungibleV2 { Seq(initFunc), Seq(supersedeFunc, issueFunc, updateListFunc, sendBlacklistFunc, transferBlacklistFunc, depositBlacklistFunc, withdrawBlacklistFunc), - Seq(issuerStateVar.arr, makerStateVar.arr), + Seq(issuerStateVar.arr, makerStateVar.arr, regulatorStateVar.arr), Seq(listMap.arr), Seq(triggerTextual, descriptorBlacklistTextual, stateVarTextual, stateMapBlacklistTextual) ).explicitGet() // StateVar - val stateVarName = List("issuer", "maker") + val stateVarName = List("issuer", "maker", "regulator") val issuerStateVar: StateVar = StateVar(0.toByte, DataType.Address.id.toByte) val makerStateVar: StateVar = StateVar(1.toByte, DataType.Address.id.toByte) + val regulatorStateVar: StateVar = StateVar(2.toByte, DataType.Address.id.toByte) lazy val stateVarTextual: Array[Byte] = Deser.serializeArrays(stateVarName.map(x => Deser.serilizeString(x))) // StateMap @@ -45,20 +46,22 @@ object ContractNonFungibleV2 { val initOpcs: Seq[Array[Byte]] = Seq( loadSigner ++ Array(0.toByte), cdbvSet ++ Array(issuerStateVar.index, 0.toByte), - cdbvSet ++ Array(makerStateVar.index, 0.toByte)) + cdbvSet ++ Array(makerStateVar.index, 0.toByte), + cdbvSet ++ Array(regulatorStateVar.index, 0.toByte)) lazy val initFunc: Array[Byte] = getFunctionBytes(initId, onInitTriggerType, nonReturnType, initDataType, initOpcs) lazy val initFuncBytes: Array[Byte] = textualFunc("init", Seq(), initPara) // Functions // Supersede val supersedeId: Short = 0 - val supersedePara: Seq[String] = Seq("newIssuer", + val supersedePara: Seq[String] = Seq("newIssuer", "newRegulator", "maker") - val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte) + val supersedeDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Account.id.toByte) val supersedeOpcs: Seq[Array[Byte]] = Seq( - cdbvrGet ++ Array(makerStateVar.index, 1.toByte), - assertSigner ++ Array(1.toByte), - cdbvSet ++ Array(issuerStateVar.index, 0.toByte)) + cdbvrGet ++ Array(makerStateVar.index, 2.toByte), + assertSigner ++ Array(2.toByte), + cdbvSet ++ Array(issuerStateVar.index, 0.toByte), + cdbvSet ++ Array(regulatorStateVar.index, 1.toByte)) lazy val supersedeFunc: Array[Byte] = getFunctionBytes(supersedeId, publicFuncType, nonReturnType, supersedeDataType, supersedeOpcs) val supersedeFuncBytes: Array[Byte] = textualFunc("supersede", Seq(), supersedePara) @@ -80,10 +83,10 @@ object ContractNonFungibleV2 { // update list val updateListId: Short = 2 val updateListPara: Seq[String] = Seq("userAccount", "value", - "issuer") + "regulator") val updateListDataType: Array[Byte] = Array(DataType.Account.id.toByte, DataType.Boolean.id.toByte) val updateListOpcs: Seq[Array[Byte]] = Seq( - cdbvrGet ++ Array(issuerStateVar.index, 2.toByte), + cdbvrGet ++ Array(regulatorStateVar.index, 2.toByte), assertCaller ++ Array(2.toByte), cdbvMapSet ++ Array(listMap.index, 0.toByte, 1.toByte) ) From f4eada490b5a86270a46275726a33cf2b8c46c1e Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 13 Apr 2021 14:22:32 +0800 Subject: [PATCH 318/391] update supersedeDataStackGen --- .../blockchain/contract/token/TokenContractV2Gen.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala index c9b09010c..30e43c5c3 100644 --- a/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala +++ b/src/test/scala/vsys/blockchain/contract/token/TokenContractV2Gen.scala @@ -11,6 +11,11 @@ trait TokenContractV2Gen extends TokenContractGen { val updateListIndex: Short = 3 + def supersedeDataStackGen(address1: Address, address2: Address): Gen[Seq[DataEntry]] = for { + add1 <- Gen.const(DataEntry(address1.bytes.arr, DataType.Address)) + add2 <- Gen.const(DataEntry(address2.bytes.arr, DataType.Address)) + } yield Seq(add1, add2) + def updateListDataStackGen(user: Address, value: Boolean): Gen[Seq[DataEntry]] = for { u <- Gen.const(DataEntry(user.bytes.arr, DataType.Address)) b: Byte = if (value) 1.toByte else 0.toByte @@ -27,6 +32,11 @@ trait TokenContractV2Gen extends TokenContractGen { if (white) ContractTokenV2.contractTokenWhiteList else ContractTokenV2.contractTokenBlackList + def supersedeTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, add1: Address, add2: Address, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { + data: Seq[DataEntry] <- supersedeDataStackGen(add1, add2) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, supersedeIndex, data, attachment, fee, feeScale, ts).explicitGet() + def updateListTokenGen(signer: PrivateKeyAccount, contractId: ContractAccount, user: Address, value: Boolean, attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { data: Seq[DataEntry] <- updateListDataStackGen(user, value) From 66ccd58e7b27c7a7a0d5d4c1bed885d2a8e42012 Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 13 Apr 2021 14:23:49 +0800 Subject: [PATCH 319/391] update token v2 test --- .../contract/token/ExecuteTokenContractV2DiffTest.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala index 0a2bb2da7..691efa93a 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2DiffTest.scala @@ -45,7 +45,7 @@ class ExecuteTokenContractV2DiffTest extends PropSpec descEx <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) updateList <- updateListTokenGen(master, contractId, master.toAddress, true, descEx, feeEx, ts + 1) updateList2 <- updateListTokenGen(master, contractId, user.toAddress, true, descEx, feeEx, ts + 2) - supersede <- supersedeTokenGen(master, contractId, user.toAddress, descEx, feeEx, ts + 3) + supersede <- supersedeTokenGen(master, contractId, user.toAddress, user.toAddress, descEx, feeEx, ts + 3) issue <- issueTokenGen(user, contractId, 10000L, descEx, feeEx, ts + 4) destroy <- destroyTokenGen(user, contractId, 100L, descEx, feeEx, ts + 5) send <- sendTokenGen(user, contractId, master.toAddress, 500L, descEx, feeEx, ts + 6) @@ -120,7 +120,7 @@ class ExecuteTokenContractV2DiffTest extends PropSpec descEx <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) updateList <- updateListTokenGen(master, contractId, master.toAddress, false, descEx, feeEx, ts + 1) updateList2 <- updateListTokenGen(master, contractId, user.toAddress, false, descEx, feeEx, ts + 2) - supersede <- supersedeTokenGen(master, contractId, user.toAddress, descEx, feeEx, ts + 3) + supersede <- supersedeTokenGen(master, contractId, user.toAddress, user.toAddress, descEx, feeEx, ts + 3) issue <- issueTokenGen(user, contractId, 10000L, descEx, feeEx, ts + 4) destroy <- destroyTokenGen(user, contractId, 100L, descEx, feeEx, ts + 5) send <- sendTokenGen(user, contractId, master.toAddress, 500L, descEx, feeEx, ts + 6) @@ -194,7 +194,7 @@ class ExecuteTokenContractV2DiffTest extends PropSpec regContract <- registerTokenGen(master, contract, dataStack, description, fee, ts) contractId = regContract.contractId description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) - executeContractSupersede <- supersedeTokenGen(master, contractId, newIssuer.toAddress, description, fee, ts) + executeContractSupersede <- supersedeTokenGen(master, contractId, newIssuer.toAddress, newIssuer.toAddress, description, fee, ts) executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) executeContractIssue1 <- issueTokenGen(newIssuer, contractId, 100000L, description, fee, ts) executeContractDestroy <- destroyTokenGen(master, contractId, 10000L, description, fee, ts) @@ -375,7 +375,7 @@ class ExecuteTokenContractV2DiffTest extends PropSpec regContract <- registerTokenGen(master, contract, dataStack, description, fee, ts) contractId = regContract.contractId description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) - executeContractSupersede <- supersedeTokenGen(master, contractId, newIssuer.toAddress, description, fee, ts) + executeContractSupersede <- supersedeTokenGen(master, contractId, newIssuer.toAddress, newIssuer.toAddress, description, fee, ts) executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) executeContractIssue1 <- issueTokenGen(newIssuer, contractId, 100000L, description, fee, ts) executeContractDestroy <- destroyTokenGen(master, contractId, 10000L, description, fee, ts) From 29163604d886f9c4ed2c37cb675f99c37713fe2c Mon Sep 17 00:00:00 2001 From: Icermli Date: Tue, 13 Apr 2021 14:24:14 +0800 Subject: [PATCH 320/391] update token v2 invalid test --- .../token/ExecuteTokenContractV2InvalidDiffTest.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala index 1c6e0d314..35efdd7c5 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractV2InvalidDiffTest.scala @@ -43,7 +43,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec descEx <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) dataForIssueDestorySplit: Seq[DataEntry] <- amountDataStackGen(10000L) dataForSend: Seq[DataEntry] <- sendDataStackGen(rep, 100L) - dataForSupersede: Seq[DataEntry] <- addressDataStackGen(rep) + dataForSupersede: Seq[DataEntry] <- supersedeDataStackGen(rep, rep) invalidIssue: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, contractId, issueIndex, dataForSend, descEx, fee, feeScale, ts + 1000).explicitGet() invalidUpdateList: ExecuteContractFunctionTransaction = ExecuteContractFunctionTransaction.create(master, @@ -204,7 +204,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec contractId = regContract.contractId contractId2 = regContract2.contractId description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) - invalidSupersede <- supersedeTokenGen(newIssuer, contractId, newIssuer.toAddress, description, fee, ts) + invalidSupersede <- supersedeTokenGen(newIssuer, contractId, newIssuer.toAddress, newIssuer.toAddress, description, fee, ts) executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) invalidIssue <- issueTokenGen(master, contractId, 100000001L, description, fee, ts) invalidDestroy <- destroyTokenGen(master, contractId, 100001L, description, fee, ts) @@ -477,7 +477,7 @@ class ExecuteTokenContractV2InvalidDiffTest extends PropSpec contractId = regContract.contractId contractId2 = regContract2.contractId description <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) - invalidSupersede <- supersedeTokenGen(newIssuer, contractId, newIssuer.toAddress, description, fee, ts) + invalidSupersede <- supersedeTokenGen(newIssuer, contractId, newIssuer.toAddress, newIssuer.toAddress, description, fee, ts) executeContractIssue <- issueTokenGen(master, contractId, 100000L, description, fee, ts) invalidIssue <- issueTokenGen(master, contractId, 100000001L, description, fee, ts) invalidDestroy <- destroyTokenGen(master, contractId, 100001L, description, fee, ts) From 6c43f7c3830e3fb1b5386e2875f4793cfbf7f93b Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 14 Apr 2021 10:24:01 +0800 Subject: [PATCH 321/391] fix check logic --- .../scala/vsys/blockchain/state/diffs/CommonValidation.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala b/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala index 01b206a42..ff39f6838 100644 --- a/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala +++ b/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala @@ -43,9 +43,8 @@ object CommonValidation { if (h <= settings.allowContractTransactionAfterHeight) Left(GenericError(s"must not appear before height=${settings.allowContractTransactionAfterHeight}")) else if (h <= settings.allowDepositWithdrawContractAfterHeight && - (c == ContractLock.contract || - c == ContractNonFungible.contract || - c == ContractPaymentChannel.contract)) + (c != ContractPermitted.contract && + c != ContractPermitted.contractWithoutSplit)) Left(GenericError(s"deposit withdraw contracts must not appear before height=${settings.allowDepositWithdrawContractAfterHeight}")) else Right(tx) } From c1daa5bec33c91fd0a2e7cb3ad98b84ba56e8f84 Mon Sep 17 00:00:00 2001 From: zl730 Date: Wed, 14 Apr 2021 11:07:39 +0800 Subject: [PATCH 322/391] close pear database on shutdown --- src/main/scala/vsys/Application.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/vsys/Application.scala b/src/main/scala/vsys/Application.scala index 4e1e06735..9a2fbef50 100644 --- a/src/main/scala/vsys/Application.scala +++ b/src/main/scala/vsys/Application.scala @@ -143,6 +143,7 @@ class Application(val actorSystem: ActorSystem, val settings: VsysSettings) exte // on unexpected shutdown sys.addShutdownHook { network.shutdown() + peerDatabase.close() shutdown() } From 47bc903512fa1609f5d8a40a411962c884827ae2 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Wed, 14 Apr 2021 12:39:23 +0800 Subject: [PATCH 323/391] Fixed PublicKey data type of the returning json value in DataEntry --- src/main/scala/vsys/blockchain/contract/DataEntry.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/DataEntry.scala b/src/main/scala/vsys/blockchain/contract/DataEntry.scala index bcc9f5ecb..d0ae1d30a 100644 --- a/src/main/scala/vsys/blockchain/contract/DataEntry.scala +++ b/src/main/scala/vsys/blockchain/contract/DataEntry.scala @@ -25,7 +25,7 @@ case class DataEntry(data: Array[Byte], private def toJson(d: Array[Byte], t: DataType.Value): JsValue = { t match { - case DataType.PublicKey => Json.toJson(PublicKeyAccount(d).address) + case DataType.PublicKey => Json.toJson(Base58.encode(PublicKeyAccount(d).publicKey)) case DataType.Address => Json.toJson(Address.fromBytes(d).right.get.address) case DataType.Amount => Json.toJson(Longs.fromByteArray(d)) case DataType.Int32 => Json.toJson(Ints.fromByteArray(d)) From f2906ea09e99458e43cac1f697d96a0a05e2e08e Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 19 Apr 2021 11:22:47 +0800 Subject: [PATCH 324/391] update contract type info --- .../api/http/contract/ContractApiRoute.scala | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index 14527d420..af7a4efbb 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -152,17 +152,26 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx } } - private def typeFromBytes(bytes: ByteStr): String = bytes match { - 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" - } + private val contractType: Map[ByteStr, String] = Map( + ContractPermitted.contract.bytes -> "TokenContractWithSplit", + ContractPermitted.contractWithoutSplit.bytes -> "TokenContract", + ContractSystem.contract.bytes -> "SystemContract", + ContractLock.contract.bytes -> "LockContract", + ContractNonFungible.contract.bytes -> "NonFungibleContract", + ContractPaymentChannel.contract.bytes -> "PaymentChannelContract", + ContractAtomicSwap.contract.bytes -> "AtomicSwapContract", + ContractVSwap.contract.bytes -> "VSwapContract", + ContractVOption.contract.bytes -> "VOptionContract", + ContractVStableSwap.contract.bytes -> "VStableSwapContract", + ContractVEscrow.contract.bytes -> "ESCROWContract", + ContractTokenV2.contractTokenWhiteList.bytes -> "TokenContractWithWhitelist", + ContractTokenV2.contractTokenBlackList.bytes -> "TokenContractWithBlacklist", + ContractNonFungibleV2.contractNFTWhitelist.bytes -> "NFTContractWithWhitelist", + ContractNonFungibleV2.contractNFTBlacklist.bytes -> "NFTContractWithBlacklist" + ) + + private def typeFromBytes(bytes: ByteStr): String = + contractType.getOrElse(bytes, "GeneralContract") @Path("/tokenInfo/{tokenId}") @ApiOperation(value = "Token's Info", notes = "Token's info by given token", httpMethod = "Get") From cf09a76299ba0595ada6fc67dc29d7f6666f3dff Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 19 Apr 2021 11:23:41 +0800 Subject: [PATCH 325/391] add more contract supported --- .../vsys/blockchain/contract/Contract.scala | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/Contract.scala b/src/main/scala/vsys/blockchain/contract/Contract.scala index 3fec412c7..93c309b72 100644 --- a/src/main/scala/vsys/blockchain/contract/Contract.scala +++ b/src/main/scala/vsys/blockchain/contract/Contract.scala @@ -79,6 +79,22 @@ object Contract extends ScorexLogging { val LanguageVersionByteLength = 4 val LanguageCodeByte: Array[Byte] = Deser.serilizeString("vdds") val LanguageVersionByte: Array[Byte] = Ints.toByteArray(1) + val validContractBytesList: Seq[Array[Byte]] = Seq( + ContractPermitted.contract.bytes.arr, + ContractPermitted.contractWithoutSplit.bytes.arr, + ContractLock.contract.bytes.arr, + ContractNonFungible.contract.bytes.arr, + ContractPaymentChannel.contract.bytes.arr, + ContractAtomicSwap.contract.bytes.arr, + ContractVSwap.contract.bytes.arr, + ContractVOption.contract.bytes.arr, + ContractVStableSwap.contract.bytes.arr, + ContractVEscrow.contract.bytes.arr, + ContractTokenV2.contractTokenWhiteList.bytes.arr, + ContractTokenV2.contractTokenBlackList.bytes.arr, + ContractNonFungibleV2.contractNFTWhitelist.bytes.arr, + ContractNonFungibleV2.contractNFTBlacklist.bytes.arr + ) def buildContract(languageCode: Array[Byte], languageVersion: Array[Byte], trigger: Seq[Array[Byte]], descriptor: Seq[Array[Byte]], @@ -144,15 +160,13 @@ object Contract extends ScorexLogging { def checkStateMap(stateMap: Array[Byte], keyDataType: DataType.DataTypeVal[_], valueDataType: DataType.DataTypeVal[_]): Boolean = stateMap.length == 3 && DataType.check(keyDataType.id.toByte, stateMap(1)) && DataType.check(valueDataType.id.toByte, stateMap(2)) + private def checkContractBytes(bytes: Array[Byte]): Boolean = { + validContractBytesList.forall(y => !(bytes sameElements y)) + } + private def isByteArrayValid(bytes: Array[Byte], textual: Seq[Array[Byte]]): Boolean = { val textualStr = textualFromBytes(textual) - if (!(bytes sameElements ContractPermitted.contract.bytes.arr) && - !(bytes sameElements ContractPermitted.contractWithoutSplit.bytes.arr) && - !(bytes sameElements ContractLock.contract.bytes.arr) && - !(bytes sameElements ContractNonFungible.contract.bytes.arr) && - !(bytes sameElements ContractPaymentChannel.contract.bytes.arr) && - !(bytes sameElements ContractAtomicSwap.contract.bytes.arr) && - !(bytes sameElements ContractVSwap.contract.bytes.arr)) { + if (checkContractBytes(bytes)) { log.warn(s"Illegal contract ${bytes.mkString(" ")}") false } else if (textualStr.isFailure || From ef1cfaefc86b769b150416810fb67f3ad217d2a6 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Thu, 6 May 2021 10:43:17 +0800 Subject: [PATCH 326/391] Prevent depositing into V Option Contract if any token id are the same --- .../blockchain/contract/ContractVOption.scala | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala index 571ee5a1e..21af4914c 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVOption.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVOption.scala @@ -79,7 +79,7 @@ object ContractVOption { val depositId: Short = 1 val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId") ++ Seq("baseTokenId", "targetTokenId", "optionTokenId", "proofTokenId", "isValidTokenId", - "isBaseToken", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock", + "isBaseToken", "valueFalse", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock", "isOptionToken", "optionTokenIfBlock", "isProofToken", "proofTokenIfBlock") val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) val depositTriggerOpcs: Seq[Array[Byte]] = Seq( @@ -90,37 +90,42 @@ object ContractVOption { cdbvrGet ++ Array(proofTokenIdStateVar.index, 6.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), compareBytesEqual ++ Array(2.toByte, 3.toByte, 8.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(9.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(7.toByte, 9.toByte), cdbvMapValAdd ++ Array(baseTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(9.toByte), - compareBytesEqual ++ Array(2.toByte, 4.toByte, 10.toByte), + ), DataType.OpcBlock).bytes ++ Array(10.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 11.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(7.toByte, 9.toByte), cdbvMapValAdd ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(11.toByte), - compareBytesEqual ++ Array(2.toByte, 5.toByte, 12.toByte), + ), DataType.OpcBlock).bytes ++ Array(12.toByte), + compareBytesEqual ++ Array(2.toByte, 5.toByte, 13.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(7.toByte, 9.toByte), cdbvMapValAdd ++ Array(optionTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(13.toByte), - compareBytesEqual ++ Array(2.toByte, 6.toByte, 14.toByte), + ), DataType.OpcBlock).bytes ++ Array(14.toByte), + compareBytesEqual ++ Array(2.toByte, 6.toByte, 15.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(7.toByte, 9.toByte), cdbvMapValAdd ++ Array(proofTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(7.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(15.toByte), - conditionIf ++ Array(8.toByte, 9.toByte), - conditionIf ++ Array(10.toByte, 11.toByte), - conditionIf ++ Array(12.toByte, 13.toByte), - conditionIf ++ Array(14.toByte, 15.toByte), + ), DataType.OpcBlock).bytes ++ Array(16.toByte), + conditionIf ++ Array(8.toByte, 10.toByte), + conditionIf ++ Array(11.toByte, 12.toByte), + conditionIf ++ Array(13.toByte, 14.toByte), + conditionIf ++ Array(15.toByte, 16.toByte), assertTrue ++ Array(7.toByte) ) lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) From 6cfc62f8d1bd6e84cfbeec180d9f3d8dc5fb9e77 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Thu, 6 May 2021 11:26:42 +0800 Subject: [PATCH 327/391] Add test for depositing when input token ids are the same --- .../voption/VOptionFunctionHelperGen.scala | 2 +- .../ExecuteVOptionInvalidDiffTest.scala | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/contract/voption/VOptionFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/voption/VOptionFunctionHelperGen.scala index b89e9f1c7..9590a6888 100644 --- a/src/test/scala/vsys/blockchain/contract/voption/VOptionFunctionHelperGen.scala +++ b/src/test/scala/vsys/blockchain/contract/voption/VOptionFunctionHelperGen.scala @@ -109,7 +109,7 @@ trait VOptionFunctionHelperGen extends VOptionContractGen with TokenContractGen proofTokenContractId = regProofTokenContract.contractId proofTokenId = tokenIdFromBytes(proofTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() - // register VSwap contract + // register VOption contract description <- validDescStringGen initVOptionDataStack: Seq[DataEntry] <- initVOptionDataStackGen(baseTokenId.arr, targetTokenId.arr, optionTokenId.arr, proofTokenId.arr, ts + 100, ts + 200) regVOptionContract <- registerVOptionGen(master, vOptionContract, initVOptionDataStack, description, fee + 10000000000L, ts + 4) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index 7e244be9f..bc4b59499 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -1,9 +1,13 @@ package test.scala.vsys.blockchain.state.contract.voption +import com.google.common.primitives.Ints import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.ContractGenHelper.basicContractTestGen +import vsys.blockchain.contract.DataEntry import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} import vsys.blockchain.contract.voption.{VOptionContractGen, VOptionFunctionHelperGen} import vsys.blockchain.state.diffs._ @@ -444,4 +448,38 @@ class ExecuteVOptionInvalidDiffTest extends PropSpec } } } + + val preconditionsAndVOptionDepositSameInputTokens: Gen[(GenesisTransaction, RC, RC, EC, EC)] = for { + (master, ts, fee) <- basicContractTestGen() + genesis <- genesisVOptionGen(master, ts) + user <- accountGen + genesis2 <- genesisVOptionGen(user, ts) + vOptionContract <- vOptionContractGen() + // register base token + regBaseTokenContract <- registerToken(master, 1000000000, 1000, "init", fee + 10000000000L, ts) + baseTokenContractId = regBaseTokenContract.contractId + baseTokenId = tokenIdFromBytes(baseTokenContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + // issue base token + attach <- genBoundedString(2, EC.MaxDescriptionSize) + issueBaseToken <- issueToken(master, baseTokenContractId, 1000000000, fee, ts + 5) + + // register VOption contract with same token Ids + description <- validDescStringGen + initVOptionDataStack: Seq[DataEntry] <- initVOptionDataStackGen(baseTokenId.arr, baseTokenId.arr, baseTokenId.arr, baseTokenId.arr, ts + 100, ts + 200) + regVOptionContract <- registerVOptionGen(master, vOptionContract, initVOptionDataStack, description, fee + 10000000000L, ts + 4) + vOptionContractId = regVOptionContract.contractId + + invalidDeposit <- depositToken(master, baseTokenContractId, master.toAddress.bytes.arr, vOptionContractId.bytes.arr, 1000000000, fee + 10000000000L, ts + 9) + } yield (genesis, regBaseTokenContract, regVOptionContract, issueBaseToken, invalidDeposit) + + property("unable to deposit tokens when 4 input token ids are the same") { + forAll(preconditionsAndVOptionDepositSameInputTokens) { case (genesis: GenesisTransaction, regBaseTokenContract: RC, regVOptionContract: RC, issueBaseToken: EC, + invalidDeposit: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(issueBaseToken.timestamp, Seq(regBaseTokenContract, regVOptionContract, issueBaseToken))), + TestBlock.createWithTxStatus(invalidDeposit.timestamp, Seq(invalidDeposit), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } } From 1db4387cfa6d40157337019e9fc618a4b3c1d193 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Thu, 6 May 2021 11:38:50 +0800 Subject: [PATCH 328/391] change package structure for v option test --- .../state/contract/voption/ExecuteVOptionInvalidDiffTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala index bc4b59499..858975245 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionInvalidDiffTest.scala @@ -1,4 +1,4 @@ -package test.scala.vsys.blockchain.state.contract.voption +package vsys.blockchain.state.contract.voption import com.google.common.primitives.Ints import org.scalacheck.{Gen, Shrink} From 4c50ba6f115f07cd94befb66e1b507c58e586f76 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Fri, 7 May 2021 14:59:36 +0800 Subject: [PATCH 329/391] remove unused import --- .../state/contract/swap/AtomicSwapContractDiffTest.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala index 991a6837b..5c54a7dfb 100644 --- a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala @@ -6,7 +6,6 @@ import org.scalacheck.{Gen, Shrink} import org.scalatest.{Matchers, PropSpec} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import scorex.crypto.hash.Sha256 -import vsys.account.ContractAccount import vsys.blockchain.block.TestBlock import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} From 92584c8263738c7f59f0732a7f978380efbee064 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 11 May 2021 11:39:28 +0800 Subject: [PATCH 330/391] Prevent depositing into V Swap Contract if any token id are the same --- .../blockchain/contract/ContractVSwap.scala | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 3dcf7b3cd..1d3a98e79 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -65,7 +65,7 @@ object ContractVSwap { val depositId: Short = 1 val depositPara: Seq[String] = Seq("depositor", "amount", "tokenId") ++ Seq("tokenAId", "tokenBId", "tokenLiquidityId", "isValidTokenId", - "isTokenA", "tokenAIfBlock", "isTokenB", "tokenBIfBlock", + "isTokenA", "valueFalse", "tokenAIfBlock", "isTokenB", "tokenBIfBlock", "isTokenLiquidity", "tokenLiquidityIfBlock") val depositDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) val depositTriggerOpcs: Seq[Array[Byte]] = Seq( @@ -75,29 +75,33 @@ object ContractVSwap { cdbvrGet ++ Array(tokenLiquidityIdStateVar.index, 5.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(6.toByte), compareBytesEqual ++ Array(2.toByte, 3.toByte, 7.toByte), + basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(8.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(6.toByte, 8.toByte), cdbvMapValAdd ++ Array(tokenABalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(8.toByte), - compareBytesEqual ++ Array(2.toByte, 4.toByte, 9.toByte), + ), DataType.OpcBlock).bytes ++ Array(9.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 10.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(6.toByte, 8.toByte), cdbvMapValAdd ++ Array(tokenBBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(10.toByte), - compareBytesEqual ++ Array(2.toByte, 5.toByte, 11.toByte), + ), DataType.OpcBlock).bytes ++ Array(11.toByte), + compareBytesEqual ++ Array(2.toByte, 5.toByte, 12.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( + assertEqual ++ Array(6.toByte, 8.toByte), cdbvMapValAdd ++ Array(liquidityBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(6.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(12.toByte), - conditionIf ++ Array(7.toByte, 8.toByte), - conditionIf ++ Array(9.toByte, 10.toByte), - conditionIf ++ Array(11.toByte, 12.toByte), + ), DataType.OpcBlock).bytes ++ Array(13.toByte), + conditionIf ++ Array(7.toByte, 9.toByte), + conditionIf ++ Array(10.toByte, 11.toByte), + conditionIf ++ Array(12.toByte, 13.toByte), assertTrue ++ Array(6.toByte) ) lazy val depositTrigger: Array[Byte] = getFunctionBytes(depositId, onDepositTriggerType, nonReturnType, depositDataType, depositTriggerOpcs) From 3fd94679ef61a7f300e4d8417e90acac1b9c23d0 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 11 May 2021 11:40:06 +0800 Subject: [PATCH 331/391] Add test for depositing to V Swap when input token id are the same --- .../vswap/ExecuteVSwapInvalidDiffTest.scala | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala index 516e28cda..7e44411be 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala @@ -1,11 +1,15 @@ package vsys.blockchain.state.contract.vswap +import com.google.common.primitives.Ints import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock import vsys.blockchain.contract.token.{SystemContractGen, TokenContractGen} import vsys.blockchain.contract.vswap.{VSwapContractGen, VSwapFunctionHelperGen} +import vsys.blockchain.contract.ContractGenHelper.basicContractTestGen +import vsys.blockchain.contract.DataEntry import vsys.blockchain.state.diffs._ import vsys.blockchain.transaction.contract._ import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} @@ -395,4 +399,37 @@ class ExecuteVSwapInvalidDiffTest extends PropSpec } } } + + val preconditionsAndVSwapDepositSameInputTokens: Gen[(GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- basicContractTestGen() + genesis <- genesisVSwapGen(master, ts) + vSwapContract <- vSwapContractGen() + // register base token + regTokenAContract <- registerToken(master, 1000000000, 1000, "init", fee + 10000000000L, ts) + tokenAContractId = regTokenAContract.contractId + tokenAId = tokenIdFromBytes(tokenAContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + // issue base token + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issueTokenA <- issueToken(master, tokenAContractId, 1000000000, fee, ts + 5) + + // register VSwap contract with same token Ids + description <- validDescStringGen + initVSwapDataStack: Seq[DataEntry] <- initVSwapDataStackGen(tokenAId.arr, tokenAId.arr, tokenAId.arr, 100) + regVSwapContract <- registerVSwapGen(master, vSwapContract, initVSwapDataStack, description, fee + 10000000000L, ts + 4) + vSwapContractId = regVSwapContract.contractId + + invalidDeposit <- depositToken(master, tokenAContractId, master.toAddress.bytes.arr, vSwapContractId.bytes.arr, 1000000000, fee + 10000000000L, ts + 9) + } yield (genesis, regTokenAContract, regVSwapContract, issueTokenA, invalidDeposit) + + property("unable to deposit tokens when 3 input token ids are the same") { + forAll(preconditionsAndVSwapDepositSameInputTokens) { case (genesis: GenesisTransaction, regTokenAContract: RegisterContractTransaction, regVSwapContract: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + invalidDeposit: ExecuteContractFunctionTransaction) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(issueTokenA.timestamp, Seq(regTokenAContract, regVSwapContract, issueTokenA))), + TestBlock.createWithTxStatus(invalidDeposit.timestamp, Seq(invalidDeposit), TransactionStatus.Failed)) { (blockDiffEi) => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } } \ No newline at end of file From c57ce8d8de7aaefdce5b55cf9d18eab4d223ea7d Mon Sep 17 00:00:00 2001 From: twwu123 Date: Wed, 12 May 2021 17:43:23 +0800 Subject: [PATCH 332/391] update V Option unit tests --- .../voption/ExecuteVOptionValidDiffTest.scala | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala index 4124f8a21..e2ea6f7d0 100644 --- a/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/voption/ExecuteVOptionValidDiffTest.scala @@ -208,11 +208,16 @@ class ExecuteVOptionValidDiffTest extends PropSpec val vOptionContractId = registerVOption.contractId.bytes.arr val (optionStatusKey, maxIssueNumKey, reservedOptionKey, - reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, tokenCollectedKey) = getOptionContractStateVarKeys(vOptionContractId) + reservedProofKey, priceKey, priceUnitKey, tokenLockedKey, _) = getOptionContractStateVarKeys(vOptionContractId) val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + newState.contractNumInfo(userStateMapBaseTokenBalanceKey) shouldBe 1000L + newState.contractNumInfo(userStateMapTargetTokenBalanceKey) shouldBe 1000L + newState.contractNumInfo(userStateMapOptionTokenBalanceKey) shouldBe 0L + newState.contractNumInfo(userStateMapProofTokenBalanceKey) shouldBe 0L + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) newState.contractNumInfo(reservedOptionKey) shouldBe 1000L @@ -271,6 +276,11 @@ class ExecuteVOptionValidDiffTest extends PropSpec val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + newState.contractNumInfo(userStateMapBaseTokenBalanceKey) shouldBe 1000L + newState.contractNumInfo(userStateMapTargetTokenBalanceKey) shouldBe 500L + newState.contractNumInfo(userStateMapOptionTokenBalanceKey) shouldBe 500L + newState.contractNumInfo(userStateMapProofTokenBalanceKey) shouldBe 500L + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) newState.contractNumInfo(reservedOptionKey) shouldBe 500L // maxIssueNum 1000, mint 500 @@ -330,6 +340,11 @@ class ExecuteVOptionValidDiffTest extends PropSpec val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + newState.contractNumInfo(userStateMapBaseTokenBalanceKey) shouldBe 1000L + newState.contractNumInfo(userStateMapTargetTokenBalanceKey) shouldBe 510L + newState.contractNumInfo(userStateMapOptionTokenBalanceKey) shouldBe 490L + newState.contractNumInfo(userStateMapProofTokenBalanceKey) shouldBe 490L + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) newState.contractNumInfo(reservedOptionKey) shouldBe 510L // maxIssueNum 1000, mint 500, unlock 10 @@ -388,6 +403,11 @@ class ExecuteVOptionValidDiffTest extends PropSpec val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + newState.contractNumInfo(userStateMapBaseTokenBalanceKey) shouldBe 899L + newState.contractNumInfo(userStateMapTargetTokenBalanceKey) shouldBe 910L + newState.contractNumInfo(userStateMapOptionTokenBalanceKey) shouldBe 90L + newState.contractNumInfo(userStateMapProofTokenBalanceKey) shouldBe 100L + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) newState.contractNumInfo(reservedOptionKey) shouldBe 910L // maxIssueNum 1000, mint 100, execute 10 @@ -449,6 +469,11 @@ class ExecuteVOptionValidDiffTest extends PropSpec val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + newState.contractNumInfo(userStateMapBaseTokenBalanceKey) shouldBe 919L + newState.contractNumInfo(userStateMapTargetTokenBalanceKey) shouldBe 608L + newState.contractNumInfo(userStateMapOptionTokenBalanceKey) shouldBe 490L + newState.contractNumInfo(userStateMapProofTokenBalanceKey) shouldBe 400L + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(1000L), DataType.Amount)) newState.contractNumInfo(reservedOptionKey) shouldBe 510L // maxIssueNum 1000, mint 500, execute 10 @@ -482,9 +507,9 @@ class ExecuteVOptionValidDiffTest extends PropSpec Long.MaxValue, // optionTokenDepositAmount Long.MaxValue) // proofTokenDepositAmount - activateOption <- activateVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, Long.MaxValue, 1L, attach, fee, ts + 13) + activateOption <- activateVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, Long.MaxValue, Long.MaxValue, attach, fee, ts + 13) mintOption <- mintVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, attach, fee, ts + 14) - executeOption <- executeVOptionGen(master, regVOptionContract.contractId, Long.MaxValue, attach, fee, ts + 101) + executeOption <- executeVOptionGen(master, regVOptionContract.contractId, Long.MaxValue - 1, attach, fee, ts + 101) } yield (genesis, regBaseTokenContract, regTargetTokenContract, regOptionTokenContract, regProofTokenContract, regVOptionContract, issueBaseToken, issueTargetToken, issueOptionToken, issueProofToken, depositBaseToken, depositTargetToken, depositOptionToken, depositProofToken, activateOption, mintOption, executeOption) @@ -510,13 +535,18 @@ class ExecuteVOptionValidDiffTest extends PropSpec val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + newState.contractNumInfo(userStateMapBaseTokenBalanceKey) shouldBe 0L + newState.contractNumInfo(userStateMapTargetTokenBalanceKey) shouldBe Long.MaxValue - 1 + newState.contractNumInfo(userStateMapOptionTokenBalanceKey) shouldBe 1L + newState.contractNumInfo(userStateMapProofTokenBalanceKey) shouldBe Long.MaxValue + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) - newState.contractNumInfo(reservedOptionKey) shouldBe Long.MaxValue + newState.contractNumInfo(reservedOptionKey) shouldBe Long.MaxValue - 1 newState.contractNumInfo(reservedProofKey) shouldBe 0L newState.contractInfo(priceKey) shouldBe Some(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) - newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(1L), DataType.Amount)) - newState.contractNumInfo(tokenLockedKey) shouldBe 0L + newState.contractInfo(priceUnitKey) shouldBe Some(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) + newState.contractNumInfo(tokenLockedKey) shouldBe 1L val master = registerVOption.proofs.firstCurveProof.explicitGet().publicKey @@ -594,6 +624,11 @@ class ExecuteVOptionValidDiffTest extends PropSpec val (userStateMapBaseTokenBalanceKey, userStateMapTargetTokenBalanceKey, userStateMapOptionTokenBalanceKey, userStateMapProofTokenBalanceKey) = getOptionContractStateMapKeys(vOptionContractId, user) + newState.contractNumInfo(userStateMapBaseTokenBalanceKey) shouldBe Long.MaxValue + newState.contractNumInfo(userStateMapTargetTokenBalanceKey) shouldBe Long.MaxValue + newState.contractNumInfo(userStateMapOptionTokenBalanceKey) shouldBe Long.MaxValue + newState.contractNumInfo(userStateMapProofTokenBalanceKey) shouldBe 0L + newState.contractInfo(optionStatusKey) shouldBe Some(DataEntry(Array(1.toByte), DataType.Boolean)) newState.contractInfo(maxIssueNumKey) shouldBe Some(DataEntry(Longs.toByteArray(Long.MaxValue), DataType.Amount)) newState.contractNumInfo(reservedOptionKey) shouldBe 0L From 619e14816874bbc2eae5ce4fc2f1dbafa72910a9 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 11 Jun 2021 10:25:35 +0800 Subject: [PATCH 333/391] add exchange contracts related settings --- src/main/scala/vsys/settings/BlockchainSettings.scala | 9 ++++++--- .../vsys/settings/BlockchainSettingsSpecification.scala | 4 ++++ .../scala/vsys/settings/TestFunctionalitySettings.scala | 6 ++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/settings/BlockchainSettings.scala b/src/main/scala/vsys/settings/BlockchainSettings.scala index 5610f2fb7..336e1a748 100644 --- a/src/main/scala/vsys/settings/BlockchainSettings.scala +++ b/src/main/scala/vsys/settings/BlockchainSettings.scala @@ -8,7 +8,8 @@ import net.ceedubs.ficus.readers.EnumerationReader._ case class FunctionalitySettings(numOfSlots: Int, mintingSpeed: Int, allowContractTransactionAfterHeight: Int, - allowDepositWithdrawContractAfterHeight: Int) + allowDepositWithdrawContractAfterHeight: Int, + allowExchangeContractAfterHeight: Int) object FunctionalitySettings { val MAINNET = FunctionalitySettings( @@ -17,7 +18,8 @@ object FunctionalitySettings { //TODO //set the value allowContractTransactionAfterHeight = 6100000, - allowDepositWithdrawContractAfterHeight = 13140520) + allowDepositWithdrawContractAfterHeight = 13140520, + allowExchangeContractAfterHeight = Int.MaxValue) val TESTNET = FunctionalitySettings( numOfSlots = 60, @@ -25,7 +27,8 @@ object FunctionalitySettings { //TODO //set the value allowContractTransactionAfterHeight = 4236000, - allowDepositWithdrawContractAfterHeight = 12550000) + allowDepositWithdrawContractAfterHeight = 12550000, + allowExchangeContractAfterHeight = Int.MaxValue) val configPath = "vsys.blockchain.custom.functionality" } diff --git a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala index 8ac4af525..169322d64 100644 --- a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala +++ b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala @@ -33,6 +33,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { | allow-leased-balance-transfer-until = 17 | allow-contract-transaction-after-height = 0 | allow-deposit-withdraw-contract-after-height = 0 + | allow-exchange-contract-after-height = 0 | num-of-slots = 5 | minting-speed = 5 | } @@ -64,6 +65,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { settings.functionalitySettings.mintingSpeed should be (5) settings.functionalitySettings.allowContractTransactionAfterHeight should be (0) settings.functionalitySettings.allowDepositWithdrawContractAfterHeight should be (0) + settings.functionalitySettings.allowExchangeContractAfterHeight should be (0) settings.genesisSettings.blockTimestamp should be(1460678400000L) settings.genesisSettings.timestamp should be(1460678400000L) settings.genesisSettings.signature should be(ByteStr.decodeBase58("BASE58BLKSGNATURE").toOption) @@ -97,6 +99,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { settings.functionalitySettings.mintingSpeed should be (1) settings.functionalitySettings.allowContractTransactionAfterHeight should be (4236000) // same as the setting settings.functionalitySettings.allowDepositWithdrawContractAfterHeight should be (12550000) + settings.functionalitySettings.allowExchangeContractAfterHeight should be (Int.MaxValue) settings.genesisSettings.blockTimestamp should be(1535356447650226656L) settings.genesisSettings.timestamp should be(1535356447650226656L) settings.genesisSettings.averageBlockDelay should be(60.seconds) @@ -139,6 +142,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { settings.functionalitySettings.mintingSpeed should be (1) settings.functionalitySettings.allowContractTransactionAfterHeight should be (6100000) // same as the setting settings.functionalitySettings.allowDepositWithdrawContractAfterHeight should be (13140520) + settings.functionalitySettings.allowExchangeContractAfterHeight should be (Int.MaxValue) settings.genesisSettings.blockTimestamp should be(1543286357457333127L) settings.genesisSettings.timestamp should be(1543286357457333127L) settings.genesisSettings.signature should be(ByteStr.decodeBase58("3yYNd7quEWaWytrAug4yGwQvpL3PVJegf9d9NTv9PVE3ouBYJs5PTQqxCjd294uK1zPLj6G5Tk447LqFMWdSFvaQ").toOption) diff --git a/src/test/scala/vsys/settings/TestFunctionalitySettings.scala b/src/test/scala/vsys/settings/TestFunctionalitySettings.scala index 3b012ff45..6e41b9328 100644 --- a/src/test/scala/vsys/settings/TestFunctionalitySettings.scala +++ b/src/test/scala/vsys/settings/TestFunctionalitySettings.scala @@ -5,13 +5,15 @@ object TestFunctionalitySettings { numOfSlots = 60, // easy to test the release case later mintingSpeed = 1, allowContractTransactionAfterHeight = 0, - allowDepositWithdrawContractAfterHeight = 0 + allowDepositWithdrawContractAfterHeight = 0, + allowExchangeContractAfterHeight = 0 ) val ContractDisabled = FunctionalitySettings( numOfSlots = 60, // easy to test the release case later mintingSpeed = 1, allowContractTransactionAfterHeight = 2, - allowDepositWithdrawContractAfterHeight = 3 + allowDepositWithdrawContractAfterHeight = 3, + allowExchangeContractAfterHeight = 4 ) } \ No newline at end of file From 21c12a94637713d63ed425286a3e9a8f0c55d1d3 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 15 Jun 2021 10:30:35 +0800 Subject: [PATCH 334/391] add validation test for exchange contract settings --- .../diffs/CommonValidationContractTest.scala | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/diffs/CommonValidationContractTest.scala b/src/test/scala/vsys/blockchain/state/diffs/CommonValidationContractTest.scala index 5c41af212..89787b99c 100644 --- a/src/test/scala/vsys/blockchain/state/diffs/CommonValidationContractTest.scala +++ b/src/test/scala/vsys/blockchain/state/diffs/CommonValidationContractTest.scala @@ -9,7 +9,7 @@ import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry} import vsys.blockchain.contract.channel.PaymentChannelContractGen -import vsys.blockchain.contract.token.TokenContractGen +import vsys.blockchain.contract.token.{TokenContractGen, TokenContractV2Gen} import vsys.blockchain.transaction.contract.RegisterContractTransaction import vsys.blockchain.transaction.{GenesisTransaction, PaymentTransaction, TransactionGen} import vsys.settings.TestFunctionalitySettings @@ -20,14 +20,16 @@ class CommonValidationContractTest extends PropSpec with Matchers with TransactionGen with TokenContractGen - with PaymentChannelContractGen { + with PaymentChannelContractGen + with TokenContractV2Gen { private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) val tContract: Gen[Contract] = tokenContractGen(true) val paymentChannelContract: Gen[Contract] = paymentChannelContractGen() + val tContractV2: Gen[Contract] = tokenContractV2Gen(true) - val preconditionsAndContract: Gen[(GenesisTransaction, PaymentTransaction, RegisterContractTransaction, RegisterContractTransaction)] = for { + val preconditionsAndContract: Gen[(GenesisTransaction, PaymentTransaction, RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction)] = for { (master, ts, fee) <- ContractGenHelper.basicContractTestGen() contract <- tContract dataStack: Seq[DataEntry] <- initTokenDataStackGen(1L, 1L, "init") @@ -41,10 +43,12 @@ class CommonValidationContractTest extends PropSpec dataForPaymentChannel: Seq[DataEntry] <- initPaymentChannelContractDataStackGen(sysTokenId.arr) // Register a payment channel that supports VSYS regPaymentChannel <- registerPaymentChannelGen(master, pContract, dataForPaymentChannel, description, fee + 10000000000L, ts + 3) - } yield (genesis, transfer, regTokenContract, regPaymentChannel) + contractV2 <- tContractV2 + regTokenContractV2 <- registerTokenGen(master, contractV2, dataStack, description, fee + 10000000000L, ts + 2) + } yield (genesis, transfer, regTokenContract, regPaymentChannel, regTokenContractV2) property("disallows contract related tx before allowed height") { - forAll(preconditionsAndContract) { case (genesis, _, regToken: RegisterContractTransaction, _) => + forAll(preconditionsAndContract) { case (genesis, _, regToken: RegisterContractTransaction, _, _) => assertDiffEi(Seq(TestBlock.create(Seq(genesis))), TestBlock.create(Seq(regToken)), TestFunctionalitySettings.ContractDisabled) { blockDiffEi => blockDiffEi should produce("must not appear before height") } @@ -52,11 +56,20 @@ class CommonValidationContractTest extends PropSpec } property("disallows deposit withdraw contract related tx before allowed height") { - forAll(preconditionsAndContract) { case (g1, p, regToken: RegisterContractTransaction, regChannel: RegisterContractTransaction) => + forAll(preconditionsAndContract) { case (g1, p, regToken: RegisterContractTransaction, regChannel: RegisterContractTransaction, _) => assertDiffEi(Seq(TestBlock.create(Seq(g1)), TestBlock.create(Seq(p))), TestBlock.create(Seq(regToken, regChannel)), TestFunctionalitySettings.ContractDisabled) { blockDiffEi => blockDiffEi should produce("deposit withdraw contracts must not appear before height") } } } + property("disallows exchange contract related tx before allowed height") { + forAll(preconditionsAndContract) { case (g1, p, regToken: RegisterContractTransaction, regChannel: RegisterContractTransaction, regTokenV2: RegisterContractTransaction) => + assertDiffEi(Seq(TestBlock.create(Seq(g1)), TestBlock.create(Seq(p)), TestBlock.create(Seq(regToken))), + TestBlock.create(Seq(regChannel, regTokenV2)), TestFunctionalitySettings.ContractDisabled) { blockDiffEi => + blockDiffEi should produce("exchange contracts must not appear before height") + } + } + } + } From 95b8b079fd52f22e0b1c7e6b1913b8d630c20a58 Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 21 Jun 2021 10:37:49 +0800 Subject: [PATCH 335/391] update version 0.3.3 tag --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3a4397c6f..d8047dbd1 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ enablePlugins(sbtdocker.DockerPlugin, JavaServerAppPackaging, JDebPackaging, Sys name := "vsys" organization := "systems.v" -version := "0.3.2" +version := "0.3.3" scalaVersion in ThisBuild := "2.12.6" crossPaths := false publishArtifact in (Compile, packageDoc) := false From c44bf042a26cb6813804eb3e23185d0fd2e5d78c Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 22 Jun 2021 11:22:04 +0800 Subject: [PATCH 336/391] remove duplicate token id check in withdraw trigger from v stable swap --- .../blockchain/contract/ContractVStableSwap.scala | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 8738ec58d..0a8929159 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -133,24 +133,21 @@ object ContractVStableSwap { cdbvrGet ++ Array(targetTokenIdStateVar.index, 4.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(5.toByte), compareBytesEqual ++ Array(2.toByte, 3.toByte, 6.toByte), - basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(7.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( - assertEqual ++ Array(5.toByte, 7.toByte), cdbvMapValMinus ++ Array(baseTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(8.toByte), - compareBytesEqual ++ Array(2.toByte, 4.toByte, 9.toByte), + ), DataType.OpcBlock).bytes ++ Array(7.toByte), + compareBytesEqual ++ Array(2.toByte, 4.toByte, 8.toByte), basicConstantGet ++ DataEntry(genFunctionOpcs( Seq( - assertEqual ++ Array(5.toByte, 7.toByte), cdbvMapValMinus ++ Array(targetTokenBalanceMap.index, 0.toByte, 1.toByte), basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(5.toByte), ) - ), DataType.OpcBlock).bytes ++ Array(10.toByte), - conditionIf ++ Array(6.toByte, 8.toByte), - conditionIf ++ Array(9.toByte, 10.toByte), + ), DataType.OpcBlock).bytes ++ Array(9.toByte), + conditionIf ++ Array(6.toByte, 7.toByte), + conditionIf ++ Array(8.toByte, 9.toByte), assertTrue ++ Array(5.toByte) ) lazy val withdrawTrigger: Array[Byte] = getFunctionBytes(withdrawId, onWithDrawTriggerType, nonReturnType, withdrawDataType, withdrawTriggerOpcs) From 16f37c0067c2e3c0d6ed801ed8b7cb3a8afc199d Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 22 Jun 2021 14:23:18 +0800 Subject: [PATCH 337/391] add unit tests for duplicated token ids in v stable swap contract --- .../ExecuteVStableSwapInvalidDiffTest.scala | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala index da648dff2..a56c3b7c2 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vstableswap/ExecuteVStableSwapInvalidDiffTest.scala @@ -1,9 +1,12 @@ package vsys.blockchain.state.contract.vstableswap +import com.google.common.primitives.Ints import org.scalacheck.{Gen, Shrink} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.ContractGenHelper.basicContractTestGen import vsys.blockchain.contract.token.SystemContractGen import vsys.blockchain.contract.vstableswap.{VStableSwapContractGen, VStableSwapFunctionHelperGen} import vsys.blockchain.state.diffs._ @@ -284,4 +287,44 @@ class ExecuteVStableSwapInvalidDiffTest extends PropSpec } } } + + val preconditionsAndVStableSwapSameTokenId: Gen[(GenesisTransaction, RC, RC, EC, EC, EC, EC)] = for { + (master, ts, fee) <- basicContractTestGen() + genesis <- genesisVStableSwapGen(master, ts) + vStableSwapContract <- vStableSwapContractGen() + // Register base token + regTokenBase <- registerToken(master, 1000000, 100, "init", fee, ts) + tokenBaseContractId = regTokenBase.contractId + tokenBaseId = tokenIdFromBytes(tokenBaseContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + description <- validDescStringGen + initVStableSwapDataStack <- initVStableSwapDataStackGen(tokenBaseId.arr, tokenBaseId.arr, 5, 1, 1) + regVStableSwapContract <- registerVStableSwapGen(master, vStableSwapContract, initVStableSwapDataStack, description, fee, ts + 2) + issueTokenBase <- issueToken(master, tokenBaseContractId, 1000000, fee, ts + 3) + depositBase <- depositToken(master, tokenBaseContractId, master.toAddress.bytes.arr, regVStableSwapContract.contractId.bytes.arr, 1000, fee, ts + 4) + withdrawBase0 <- withdrawToken(master, tokenBaseContractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 0, fee, ts + 5) + withdrawBaseInvalid <- withdrawToken(master, tokenBaseContractId, regVStableSwapContract.contractId.bytes.arr, master.toAddress.bytes.arr, 1000, fee, ts + 5) + } yield (genesis, regTokenBase, regVStableSwapContract, issueTokenBase, depositBase, withdrawBase0, withdrawBaseInvalid) + + property("unable to deposit when token id is duplicated") { + forAll(preconditionsAndVStableSwapSameTokenId) { case (genesis: GenesisTransaction, regBase: RC, regVStableSwap: RC, issueBase: EC, depositBase: EC, _, _) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(issueBase.timestamp, Seq(regBase, regVStableSwap, issueBase))), + TestBlock.createWithTxStatus(depositBase.timestamp, Seq(depositBase), TransactionStatus.Failed)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + + forAll(preconditionsAndVStableSwapSameTokenId) { case (genesis: GenesisTransaction, regBase: RC, regVStableSwap: RC, issueBase: EC, _, withdraw0: EC, _) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(issueBase.timestamp, Seq(regBase, regVStableSwap, issueBase))), + TestBlock.createWithTxStatus(withdraw0.timestamp, Seq(withdraw0), TransactionStatus.Success)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + + forAll(preconditionsAndVStableSwapSameTokenId) { case (genesis: GenesisTransaction, regBase: RC, regVStableSwap: RC, issueBase: EC, _, _, withdrawInvalid: EC) => + assertDiffEi(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(issueBase.timestamp, Seq(regBase, regVStableSwap, issueBase))), + TestBlock.createWithTxStatus(withdrawInvalid.timestamp, Seq(withdrawInvalid), TransactionStatus.ContractTokenBalanceInsufficient)) { blockDiffEi => + blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient + } + } + } } From d8d917b0cfdb67c99016376b8c1b7f149cfe50eb Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 14:58:16 +0800 Subject: [PATCH 338/391] Add generation functions for V Escrow testing --- .../contract/vescrow/VEscrowContractGen.scala | 316 ++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/vescrow/VEscrowContractGen.scala diff --git a/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowContractGen.scala b/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowContractGen.scala new file mode 100644 index 000000000..170b756b5 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowContractGen.scala @@ -0,0 +1,316 @@ +package vsys.blockchain.contract.vescrow + +import com.google.common.primitives.Longs +import org.scalacheck.Gen +import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.ContractGenHelper.{ENOUGH_AMT, feeScale} +import vsys.blockchain.contract.{Contract, ContractVEscrow, DataEntry, DataType} +import vsys.blockchain.state._ +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +trait VEscrowContractGen { + + val supersedeIndex: Short = 0 + val createIndex: Short = 1 + val recipientDepositIndex: Short = 2 + val judgeDepositIndex: Short = 3 + val payerCancelIndex: Short = 4 + val recipientCancelIndex: Short = 5 + val judgeCancelIndex: Short = 6 + val submitWorkIndex: Short = 7 + val approveWorkIndex: Short = 8 + val applyToJudgeIndex: Short = 9 + val judgeIndex: Short = 10 + val submitPenaltyIndex: Short = 11 + val payerRefundIndex: Short = 12 + val recipientRefundIndex: Short = 13 + val collectIndex: Short = 14 + + def vEscrowContractGen(): Gen[Contract] = ContractVEscrow.contract + + def genesisVEscrowGen(rep: PrivateKeyAccount, + ts: Long): Gen[GenesisTransaction] = + GenesisTransaction.create(rep, ENOUGH_AMT, -1, ts).explicitGet() + + def registerVEscrowGen(signer: PrivateKeyAccount, + contract: Contract, + dataStack: Seq[DataEntry], + description: String, + fee: Long, + ts: Long): Gen[RegisterContractTransaction] = + RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() + + def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + addr <- Gen.const(DataEntry.create(address.bytes.arr, DataType.Address).right.get) + } yield Seq(addr) + + def createDataStackGen(recipient: Address, + amount: Long, + repDeposit: Long, + judgeDeposit: Long, + fee: Long, + refund: Long, + expirationTime: Long): Gen[Seq[DataEntry]] = for { + recipient <- Gen.const(DataEntry.create(recipient.bytes.arr, DataType.Address).right.get) + amount <- Gen.const(DataEntry.create(Longs.toByteArray(amount), DataType.Amount).right.get) + repDeposit <- Gen.const(DataEntry.create(Longs.toByteArray(repDeposit), DataType.Amount).right.get) + judgeDeposit <- Gen.const(DataEntry.create(Longs.toByteArray(judgeDeposit), DataType.Amount).right.get) + fee <- Gen.const(DataEntry.create(Longs.toByteArray(fee), DataType.Amount).right.get) + refund <- Gen.const(DataEntry.create(Longs.toByteArray(refund), DataType.Amount).right.get) + expirationTime <- Gen.const(DataEntry.create(Longs.toByteArray(expirationTime), DataType.Amount).right.get) + } yield Seq(recipient, amount, repDeposit, judgeDeposit, fee, refund, expirationTime) + + def escrowDepositDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def escrowCancelDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def submitWorkDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def approveWorkDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def applyToJudgeDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def judgeDataStackGen(orderId: Array[Byte], + payerAmount: Long, + recipientAmount: Long): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + payerAmount <- Gen.const(DataEntry.create(Longs.toByteArray(payerAmount), DataType.Amount).right.get) + recipientAmount <- Gen.const(DataEntry.create(Longs.toByteArray(recipientAmount), DataType.Amount).right.get) + } yield Seq(orderId, payerAmount, recipientAmount) + + def submitPenaltyDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def payerRefundDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def recipientRefundDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def collectDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { + orderId <- Gen.const(DataEntry.create(orderId, DataType.ShortBytes).right.get) + } yield Seq(orderId) + + def initVEscrowDataStackGen(tokenId: Array[Byte], duration: Long, judgeDuration: Long): Gen[Seq[DataEntry]] = for { + tokenId <- Gen.const(DataEntry.create(tokenId, DataType.TokenId).right.get) + duration <- Gen.const(DataEntry.create(Longs.toByteArray(duration), DataType.Timestamp).right.get) + judgeDuration <- Gen.const(DataEntry.create(Longs.toByteArray(judgeDuration), DataType.Timestamp).right.get) + } yield Seq(tokenId, duration, judgeDuration) + + def supersedeVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + newJudge: Address, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = supersedeIndex + for { + data: Seq[DataEntry] <- addressDataStackGen(newJudge) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def createVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + recipient: Address, + amount: Long, + repDeposit: Long, + judgeDeposit: Long, + judgeFee: Long, + refund: Long, + expirationTime: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = createIndex + for { + data: Seq[DataEntry] <- createDataStackGen(recipient, amount, repDeposit, judgeDeposit, judgeFee, refund, expirationTime) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def recipientDepositVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = recipientDepositIndex + for { + data: Seq[DataEntry] <- escrowDepositDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def judgeDepositVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = judgeDepositIndex + for { + data: Seq[DataEntry] <- escrowDepositDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def payerCancelVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = payerCancelIndex + for { + data: Seq[DataEntry] <- escrowCancelDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def recipientCancelVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = recipientCancelIndex + for { + data: Seq[DataEntry] <- escrowCancelDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def judgeCancelVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = judgeCancelIndex + for { + data: Seq[DataEntry] <- escrowCancelDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def submitWorkVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = submitWorkIndex + for { + data: Seq[DataEntry] <- submitWorkDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def approveWorkVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = approveWorkIndex + for { + data: Seq[DataEntry] <- approveWorkDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def applyToJudgeVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = applyToJudgeIndex + for { + data: Seq[DataEntry] <- applyToJudgeDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def judgeVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + payerAmount: Long, + recipientAmount: Long, + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = judgeIndex + for { + data: Seq[DataEntry] <- judgeDataStackGen(orderId, payerAmount, recipientAmount) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def submitPenaltyVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = submitPenaltyIndex + for { + data: Seq[DataEntry] <- submitPenaltyDataStackGen(orderId: Array[Byte]) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def payerRefundVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = payerRefundIndex + for { + data: Seq[DataEntry] <- payerRefundDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def recipientRefundVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = recipientRefundIndex + for { + data: Seq[DataEntry] <- recipientRefundDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } + + def collectVEscrowGen(signer: PrivateKeyAccount, + contractId: ContractAccount, + orderId: Array[Byte], + attachment: Array[Byte], + fee: Long, + ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = collectIndex + for { + data: Seq[DataEntry] <- collectDataStackGen(orderId) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, + data, attachment, fee, feeScale, ts).explicitGet() + } +} \ No newline at end of file From e429903a549ae4df30270dda6b586423fb3f1303 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 15:08:20 +0800 Subject: [PATCH 339/391] Avoid inheriting function name conflicts --- .../contract/vescrow/VEscrowContractGen.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowContractGen.scala b/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowContractGen.scala index 170b756b5..60feb7323 100644 --- a/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowContractGen.scala @@ -11,7 +11,7 @@ import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, trait VEscrowContractGen { - val supersedeIndex: Short = 0 + val vEscrowsupersedeIndex: Short = 0 val createIndex: Short = 1 val recipientDepositIndex: Short = 2 val judgeDepositIndex: Short = 3 @@ -41,7 +41,7 @@ trait VEscrowContractGen { ts: Long): Gen[RegisterContractTransaction] = RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() - def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + def vEscrowAddressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { addr <- Gen.const(DataEntry.create(address.bytes.arr, DataType.Address).right.get) } yield Seq(addr) @@ -58,7 +58,7 @@ trait VEscrowContractGen { judgeDeposit <- Gen.const(DataEntry.create(Longs.toByteArray(judgeDeposit), DataType.Amount).right.get) fee <- Gen.const(DataEntry.create(Longs.toByteArray(fee), DataType.Amount).right.get) refund <- Gen.const(DataEntry.create(Longs.toByteArray(refund), DataType.Amount).right.get) - expirationTime <- Gen.const(DataEntry.create(Longs.toByteArray(expirationTime), DataType.Amount).right.get) + expirationTime <- Gen.const(DataEntry.create(Longs.toByteArray(expirationTime), DataType.Timestamp).right.get) } yield Seq(recipient, amount, repDeposit, judgeDeposit, fee, refund, expirationTime) def escrowDepositDataStackGen(orderId: Array[Byte]): Gen[Seq[DataEntry]] = for { @@ -117,9 +117,9 @@ trait VEscrowContractGen { attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { - val id: Short = supersedeIndex + val id: Short = vEscrowsupersedeIndex for { - data: Seq[DataEntry] <- addressDataStackGen(newJudge) + data: Seq[DataEntry] <- vEscrowAddressDataStackGen(newJudge) } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } From bc0eb7f67a7ed570fcccaae7b0a3148bb402abd0 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 15:08:41 +0800 Subject: [PATCH 340/391] Add test for registering V Escrow Contract --- .../RegisterVEscrowContractDiffTest.scala | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/vescrow/RegisterVEscrowContractDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/vescrow/RegisterVEscrowContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vescrow/RegisterVEscrowContractDiffTest.scala new file mode 100644 index 000000000..a417f55b3 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vescrow/RegisterVEscrowContractDiffTest.scala @@ -0,0 +1,77 @@ +package vsys.blockchain.state.contract.vescrow + +import cats.Monoid +import com.google.common.primitives.{Bytes, Ints} +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.account.ContractAccount +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract._ +import vsys.blockchain.contract.vescrow.VEscrowContractGen +import vsys.blockchain.state.diffs.assertDiffAndState +import vsys.blockchain.state.{ByteStr, Portfolio, _} +import vsys.blockchain.transaction.contract.RegisterContractTransaction +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen} + +class RegisterVEscrowContractDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with VEscrowContractGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val languageCode: String = "vdds" + val languageVersion: Int = 2 + + val preconditionsAndBuildVEscrowContract: Gen[(Array[Byte], Array[Byte], Seq[Array[Byte]], + Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]], Seq[Array[Byte]])] = for { + langCode <- ContractGenHelper.languageCodeGen(languageCode) + langVer <- ContractGenHelper.languageVersionGen(languageVersion) + init <- Gen.const(ContractVEscrow.contract.trigger) + descriptor <- Gen.const(ContractVEscrow.contract.descriptor) + stateVar <- Gen.const(ContractVEscrow.contract.stateVar) + stateMap <- Gen.const(ContractVEscrow.contract.stateMap) + textual <- Gen.const(ContractVEscrow.contract.textual) + } yield (langCode, langVer, init, descriptor, stateVar, stateMap, textual) + + property("ensure v-escrow can be built as a valid contract") { + forAll(preconditionsAndBuildVEscrowContract) { case (langCode, langVer, init, descriptor, stateVar, stateMap, textual) => + Contract.buildContract(langCode, langVer, init, descriptor, stateVar, stateMap, textual) shouldBe an[Right[_,_]] + } + } + + val validContract: Gen[Contract] = vEscrowContractGen() + val preconditionsAndRegContractTest: Gen[(GenesisTransaction, RegisterContractTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + genesis <- genesisVEscrowGen(master, ts) + contract <- validContract + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + data: Seq[DataEntry] <- initVEscrowDataStackGen(tokenId.arr, 1, 1) + description <- validDescStringGen + create <- registerVEscrowGen(master, contract, data, description, fee, ts + 1) + } yield (genesis, create) + + property("register v-escrow contract transaction doesn't break invariant") { + forAll(preconditionsAndRegContractTest) { case (genesis, reg: RegisterContractTransaction) => + assertDiffAndState(Seq(TestBlock.create(Seq(genesis))), TestBlock.create(Seq(reg))) { (blockDiff, newState) => + val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) + totalPortfolioDiff.balance shouldBe -reg.transactionFee + totalPortfolioDiff.effectiveBalance shouldBe -reg.transactionFee + val master = reg.proofs.firstCurveProof.explicitGet().publicKey + val contractId = reg.contractId.bytes + val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) + + val (_, masterTxs) = newState.accountTransactionIds(master, 2, 0) + masterTxs.size shouldBe 2 // genesis, reg + newState.contractTokens(contractId) shouldBe 0 + newState.contractContent(contractId) shouldEqual Some((2, reg.id, ContractVEscrow.contract)) + + newState.contractInfo(makerKey) shouldEqual Some(DataEntry(master.toAddress.bytes.arr, DataType.Address)) + } + } + } +} \ No newline at end of file From 02f8e295a6b880f5e92a0238effa971d1e3d8458 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 15:12:27 +0800 Subject: [PATCH 341/391] Fix contract V escrow OPCs --- .../vsys/blockchain/contract/ContractVEscrow.scala | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index d140fba14..ae60d9d8f 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -183,7 +183,6 @@ object ContractVEscrow { cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), assertTrue ++ Array(2.toByte), cdbvrMapGet ++ Array(orderDepositStatusIndex, 0.toByte, 3.toByte), - assertTrue ++ Array(3.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(4.toByte), assertEqual ++ Array(3.toByte, 4.toByte), cdbvrMapGet ++ Array(orderDepositAmountIndex, 0.toByte, 5.toByte), @@ -308,14 +307,14 @@ object ContractVEscrow { "recipient", "judge", "workAmount", "recipientLocked", "recipientAmount", "fee", "judgeLocked", "judgeAmount", "valueFalse") val approveWorkOpcs: Seq[Array[Byte]] = Seq( - cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), + cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 1.toByte), assertCaller ++ Array(1.toByte), cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), assertTrue ++ Array(2.toByte), cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 3.toByte), assertTrue ++ Array(3.toByte)) ++ timestampCheck(4, true) ++ Seq( cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 7.toByte), - cdbvrGet ++ Array(judgeStateVar.index, 0.toByte, 8.toByte), + cdbvrGet ++ Array(judgeStateVar.index, 8.toByte), cdbvrMapGet ++ Array(orderRecipientAmountMap.index, 0.toByte, 9.toByte), cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), basicAdd ++ Array(9.toByte, 10.toByte, 11.toByte), @@ -336,7 +335,7 @@ object ContractVEscrow { Seq("payer", "orderStatus", "isSubmit", "currentTime", "expirationTime", "isValidTime", "judgeStatus", "valueFalse", "judgeDuration", "time", "updateTime", "valueTrue") val applyToJudgeOpcs: Seq[Array[Byte]] = Seq( - cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), + cdbvrMapGet ++ Array(orderPayerMap.index, 0.toByte, 1.toByte), assertCaller ++ Array(1.toByte), cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), assertTrue ++ Array(2.toByte), @@ -461,9 +460,9 @@ object ContractVEscrow { cdbvrMapGet ++ Array(orderRecipientMap.index, 0.toByte, 1.toByte), assertCaller ++ Array(1.toByte), cdbvrMapGet ++ Array(orderStatusMap.index, 0.toByte, 2.toByte), - assertCaller ++ Array(2.toByte), + assertTrue ++ Array(2.toByte), cdbvrMapGet ++ Array(orderSubmitStatusMap.index, 0.toByte, 3.toByte), - assertCaller ++ Array(3.toByte), + assertTrue ++ Array(3.toByte), basicConstantGet ++ DataEntry(Array(0.toByte), DataType.Boolean).bytes ++ Array(4.toByte), cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 5.toByte), assertEqual ++ Array(4.toByte, 5.toByte)) ++ timestampCheck(6, false) ++ Seq( From 35fd1c14e5c581ff94129b126d8700ff662ab579 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 29 Jun 2021 15:15:43 +0800 Subject: [PATCH 342/391] Add NonFungibleContractV2Gen and ExecuteNonFungibleContractV2InvalidDiffTest --- .../token/NonFungibleContractV2Gen.scala | 96 +++++ ...NonFungibleContractV2InvalidDiffTest.scala | 367 ++++++++++++++++++ 2 files changed, 463 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/token/NonFungibleContractV2Gen.scala create mode 100644 src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractV2Gen.scala b/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractV2Gen.scala new file mode 100644 index 000000000..4bd88f5a0 --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/token/NonFungibleContractV2Gen.scala @@ -0,0 +1,96 @@ +package vsys.blockchain.contract.token + +import com.google.common.primitives.Ints +import org.scalacheck.Gen +import vsys.account.{Address, ContractAccount, PrivateKeyAccount} +import vsys.blockchain.contract.ContractGenHelper.{ENOUGH_AMT, feeScale} +import vsys.blockchain.contract.{Contract, ContractGenHelper, ContractNonFungibleV2, DataEntry, DataType} +import vsys.blockchain.state._ +import vsys.blockchain.transaction.GenesisTransaction +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +trait NonFungibleContractV2Gen { + val supersedeIndex: Short = 0 + val issueIndex: Short = 1 + val updateListIndex: Short = 2 + val sendIndex: Short = 3 + val transferIndex: Short = 4 + val depositIndex: Short = 5 + val withdrawIndex: Short = 6 + + def initTokenDataStackGen(): Gen[Seq[DataEntry]] = Seq() + + def issueDataStackGen(desc: String): Gen[Seq[DataEntry]] = for { + shortText <- Gen.const(DataEntry.create(desc.getBytes(), DataType.ShortText).right.get) + } yield Seq(shortText) + + def addressDataStackGen(address: Address): Gen[Seq[DataEntry]] = for { + add <- Gen.const(DataEntry(address.bytes.arr, DataType.Address)) + } yield Seq(add) + + def sendDataStackGen(recipient: Address, tokenIndex: Int): Gen[Seq[DataEntry]] = for { + reci <- Gen.const(DataEntry(recipient.bytes.arr, DataType.Address)) + toIdx <- Gen.const(DataEntry(Ints.toByteArray(tokenIndex), DataType.Int32)) + } yield Seq(reci, toIdx) + + def nonFungibleContractWhiteGen(): Gen[Contract] = ContractNonFungibleV2.contractNFTWhitelist + + def nonFungibleContractBlackGen(): Gen[Contract] = ContractNonFungibleV2.contractNFTBlacklist + + def registerNonFungibleV2Gen(signer: PrivateKeyAccount, contract: Contract, dataStack: Seq[DataEntry], + description: String, fee: Long, ts: Long): Gen[RegisterContractTransaction] = + RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() + + def genesisNonFungibleV2Gen(rep: PrivateKeyAccount, ts: Long): Gen[GenesisTransaction] = + GenesisTransaction.create(rep, ENOUGH_AMT, -1, ts).explicitGet() + + def supersedeNonFungibleV2Gen(signer: PrivateKeyAccount, contractId: ContractAccount, newAdd: Address, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { + data: Seq[DataEntry] <- addressDataStackGen(newAdd) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, supersedeIndex, data, attachment, fee, feeScale, ts).explicitGet() + + def issueNonFungibleV2Gen(signer: PrivateKeyAccount, contractId: ContractAccount, desc: String, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = for { + data: Seq[DataEntry] <- issueDataStackGen(desc) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, issueIndex, data, attachment, fee, feeScale, ts).explicitGet() + + def updateListNonFungibleV2Gen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = updateListIndex + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() + } + + def sendNonFungibleV2Gen(sender: PrivateKeyAccount, contractId: ContractAccount, rep: Address, toIdx: Int, + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = sendIndex + for { + data: Seq[DataEntry] <- sendDataStackGen(rep, toIdx) + } yield ExecuteContractFunctionTransaction.create(sender, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() + } + + def transferNonFungibleV2Gen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = transferIndex + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() + } + + def depositNonFungibleV2Gen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = depositIndex + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() + } + + def withdrawNonFungibleV2Gen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], + attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { + val id: Short = withdrawIndex + for { + data: Seq[DataEntry] <- ContractGenHelper.dataListGen(data, dataType) + } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() + } +} \ No newline at end of file diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala new file mode 100644 index 000000000..82d656afe --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala @@ -0,0 +1,367 @@ +package vsys.blockchain.state.contract.token + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.{Matchers, PropSpec} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry, DataType} +import vsys.blockchain.contract.token.NonFungibleContractV2Gen +import vsys.blockchain.state.diffs.assertDiffAndStateCorrectBlockTime +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with NonFungibleContractV2Gen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val nonFungibleWhiteContract: Gen[Contract] = nonFungibleContractWhiteGen() + val nonFungibleBlackContract: Gen[Contract] = nonFungibleContractBlackGen() + + val preconditionsNonFungibleContractV2UpdateListInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContract <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(user, contractId, updateListData, updateListType, attach, fee, ts) + } yield (genesis, genesis2, regContract, issue, updateList1, updateList2, updateList3) + + property("Execute update list in non fungible contract V2") { + forAll(preconditionsNonFungibleContractV2UpdateListInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, updateList3: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(reg.timestamp, Seq(reg, issue))), + TestBlock.createWithTxStatus(updateList1.timestamp, Seq(updateList1), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(reg.timestamp, Seq(reg, issue))), + TestBlock.createWithTxStatus(updateList2.timestamp, Seq(updateList2), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(reg.timestamp, Seq(reg, issue))), + TestBlock.createWithTxStatus(updateList3.timestamp, Seq(updateList3), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + } + } + + val preconditionsNonFungibleWhiteContractV2SendInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractWhite <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractWhiteId = regContractWhite.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractWhiteId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + send <- sendNonFungibleV2Gen(master, contractWhiteId, user, 0, attach, fee, ts) + + + } yield (genesis, genesis2, regContractWhite, issue, updateList1, updateList2, updateList3, updateList4, send) + + property("Execute send in non fungible white contract") { + forAll(preconditionsNonFungibleWhiteContractV2SendInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, + updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, send: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractWhite, issue, updateList1, updateList2))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + + // only receiver on white list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractWhite, issue, updateList1))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // only sender on white list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractWhite, issue, updateList2))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // update receiver not on white list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList3.timestamp, Seq(regContractWhite, issue, updateList1, updateList2, updateList3))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // update sender not on white list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList4.timestamp, Seq(regContractWhite, issue, updateList1, updateList2, updateList4))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsNonFungibleBlackContractV2SendInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractBlack <- nonFungibleBlackContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractBlack <- registerNonFungibleV2Gen(master, contractBlack, dataStack, description, fee + 10000000000L, ts) + contractBlackId = regContractBlack.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractBlackId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + send <- sendNonFungibleV2Gen(master, contractBlackId, user, 0, attach, fee, ts) + + + } yield (genesis, genesis2, regContractBlack, issue, updateList1, updateList2, updateList3, updateList4, send) + + property("Execute send in non fungible black contract") { + forAll(preconditionsNonFungibleBlackContractV2SendInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, + updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, send: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractBlack, issue, updateList1, updateList2))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + + // only receiver on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractBlack, issue, updateList3))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // only sender on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractBlack, issue, updateList4))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // update receiver not on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList3.timestamp, Seq(regContractBlack, issue, updateList3, updateList4, updateList1))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // update sender not on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList4.timestamp, Seq(regContractBlack, issue, updateList3, updateList4, updateList2))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsNonFungibleWhiteContractV2TransferInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractWhite <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractWhiteId = regContractWhite.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractWhiteId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + + transferData = Seq(master.toAddress.bytes.arr, user.toAddress.bytes.arr, Array(0.toByte)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Int32) + transfer <- transferNonFungibleV2Gen(master, contractWhiteId, transferData, transferType, attach, fee, ts) + + + } yield (genesis, genesis2, regContractWhite, issue, updateList1, updateList2, updateList3, updateList4, transfer) + + property("Execute transfer in non fungible white contract") { + forAll(preconditionsNonFungibleWhiteContractV2SendInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, + updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, transfer: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractWhite, issue, updateList1, updateList2))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + + // only receiver on white list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractWhite, issue, updateList1))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // only sender on white list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractWhite, issue, updateList2))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // update receiver not on white list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList3.timestamp, Seq(regContractWhite, issue, updateList1, updateList2, updateList3))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // update sender not on white list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList4.timestamp, Seq(regContractWhite, issue, updateList1, updateList2, updateList4))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + + + + + val preconditionsNonFungibleBlackContractV2TransferInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractBlack <- nonFungibleBlackContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractBlack <- registerNonFungibleV2Gen(master, contractBlack, dataStack, description, fee + 10000000000L, ts) + contractBlackId = regContractBlack.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractBlackId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + transferData = Seq(master.toAddress.bytes.arr, user.toAddress.bytes.arr, Array(0.toByte)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Int32) + transfer <- transferNonFungibleV2Gen(master, contractBlackId, transferData, transferType, attach, fee, ts) + + + } yield (genesis, genesis2, regContractBlack, issue, updateList1, updateList2, updateList3, updateList4, transfer) + + property("Execute transfer in non fungible black contract") { + forAll(preconditionsNonFungibleBlackContractV2SendInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, + updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, transfer: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractBlack, issue, updateList1, updateList2))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + + // only receiver on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractBlack, issue, updateList3))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // only sender on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractBlack, issue, updateList4))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // update receiver not on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList3.timestamp, Seq(regContractBlack, issue, updateList3, updateList4, updateList1))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // update sender not on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList4.timestamp, Seq(regContractBlack, issue, updateList3, updateList4, updateList2))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } +} \ No newline at end of file From 918399b3f309458de6fbca9e500471db91a3134e Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 29 Jun 2021 15:34:56 +0800 Subject: [PATCH 343/391] Add deposit function unit test for Non Fungible Contract V2 --- ...NonFungibleContractV2InvalidDiffTest.scala | 166 +++++++++++++++++- 1 file changed, 157 insertions(+), 9 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala index 82d656afe..072aaae4e 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala @@ -1,9 +1,12 @@ package vsys.blockchain.state.contract.token +import com.google.common.primitives.Ints import org.scalacheck.{Gen, Shrink} import org.scalatest.{Matchers, PropSpec} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.lock.LockContractGen import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry, DataType} import vsys.blockchain.contract.token.NonFungibleContractV2Gen import vsys.blockchain.state.diffs.assertDiffAndStateCorrectBlockTime @@ -15,6 +18,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec with GeneratorDrivenPropertyChecks with Matchers with TransactionGen + with LockContractGen with NonFungibleContractV2Gen { private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) @@ -244,8 +248,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec updateListType = Seq(DataType.Address, DataType.Boolean) updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) - - transferData = Seq(master.toAddress.bytes.arr, user.toAddress.bytes.arr, Array(0.toByte)) + transferData = Seq(master.toAddress.bytes.arr, user.toAddress.bytes.arr, Ints.toByteArray(0)) transferType = Seq(DataType.Address, DataType.Address, DataType.Int32) transfer <- transferNonFungibleV2Gen(master, contractWhiteId, transferData, transferType, attach, fee, ts) @@ -253,7 +256,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec } yield (genesis, genesis2, regContractWhite, issue, updateList1, updateList2, updateList3, updateList4, transfer) property("Execute transfer in non fungible white contract") { - forAll(preconditionsNonFungibleWhiteContractV2SendInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, + forAll(preconditionsNonFungibleWhiteContractV2TransferInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, transfer: ExecuteContractFunctionTransaction) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractWhite, issue, updateList1, updateList2))), @@ -287,10 +290,6 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec } } - - - - val preconditionsNonFungibleBlackContractV2TransferInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { (master, ts, fee) <- ContractGenHelper.basicContractTestGen() contractBlack <- nonFungibleBlackContract @@ -323,7 +322,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec updateListType = Seq(DataType.Address, DataType.Boolean) updateList4 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) - transferData = Seq(master.toAddress.bytes.arr, user.toAddress.bytes.arr, Array(0.toByte)) + transferData = Seq(master.toAddress.bytes.arr, user.toAddress.bytes.arr, Ints.toByteArray(0)) transferType = Seq(DataType.Address, DataType.Address, DataType.Int32) transfer <- transferNonFungibleV2Gen(master, contractBlackId, transferData, transferType, attach, fee, ts) @@ -331,7 +330,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec } yield (genesis, genesis2, regContractBlack, issue, updateList1, updateList2, updateList3, updateList4, transfer) property("Execute transfer in non fungible black contract") { - forAll(preconditionsNonFungibleBlackContractV2SendInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, + forAll(preconditionsNonFungibleBlackContractV2TransferInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, transfer: ExecuteContractFunctionTransaction) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractBlack, issue, updateList1, updateList2))), @@ -364,4 +363,153 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec } } } + + val preconditionsNonFungibleBlackContractV2DepositInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractBlack <- nonFungibleBlackContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractBlack <- registerNonFungibleV2Gen(master, contractBlack, dataStack, description, fee + 10000000000L, ts) + contractBlackId = regContractBlack.contractId + tokenId = tokenIdFromBytes(contractBlackId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + contractLock <- lockContractGen + dataStack: Seq[DataEntry] <- initLockContractDataStackGen(tokenId.arr) + description <- validDescStringGen + regContractLock <- registerLockGen(master, contractLock, dataStack, description, fee + 10000000000L, ts) + contractLockId = regContractLock.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractBlackId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + deposit <- depositNonFungibleV2Gen(master, contractBlackId, depositData, depositType, attach, fee, ts) + + depositData = Seq(user.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + depositInvalid <- depositNonFungibleV2Gen(master, contractBlackId, depositData, depositType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractBlackId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + depositInvalid2 <- depositNonFungibleV2Gen(master, contractBlackId, depositData, depositType, attach, fee, ts) + + + } yield (genesis, genesis2, regContractBlack, regContractLock, issue, updateList1, deposit, depositInvalid, depositInvalid2) + + property("Execute deposit in non fungible black contract") { + forAll(preconditionsNonFungibleBlackContractV2DepositInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, regContractLock: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, depositInvalid: ExecuteContractFunctionTransaction, depositInvalid2: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue))), + TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + + // depositor on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractBlack, regContractLock, issue, updateList1))), + TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + + // depositor on black list + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractBlack, regContractLock, issue, updateList1))), + TestBlock.createWithTxStatus(depositInvalid.timestamp, Seq(depositInvalid), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + + // deposit into a wrong contract + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractBlack, regContractLock, issue))), + TestBlock.createWithTxStatus(depositInvalid2.timestamp, Seq(depositInvalid2), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsNonFungibleWhiteContractV2DepositInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractWhite <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractWhiteId = regContractWhite.contractId + tokenId = tokenIdFromBytes(contractWhiteId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + contractLock <- lockContractGen + dataStack: Seq[DataEntry] <- initLockContractDataStackGen(tokenId.arr) + description <- validDescStringGen + regContractLock <- registerLockGen(master, contractLock, dataStack, description, fee + 10000000000L, ts) + contractLockId = regContractLock.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractWhiteId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + deposit <- depositNonFungibleV2Gen(master, contractWhiteId, depositData, depositType, attach, fee, ts) + + depositData = Seq(user.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + depositInvalid <- depositNonFungibleV2Gen(master, contractWhiteId, depositData, depositType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + depositInvalid2 <- depositNonFungibleV2Gen(master, contractWhiteId, depositData, depositType, attach, fee, ts) + + } yield (genesis, genesis2, regContractWhite, regContractLock, issue, updateList1, updateList2, updateList3, updateList4, deposit, depositInvalid, depositInvalid2) + + property("Execute deposit in non fungible white contract") { + forAll(preconditionsNonFungibleWhiteContractV2DepositInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, regContractLock: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, depositInvalid: ExecuteContractFunctionTransaction, depositInvalid2: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2))), + TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + // only update depositor to whitelist before withdraw + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1))), + TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // only update contract to whitelist before withdraw + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList2))), + TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // withdraw with a wrong caller + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2))), + TestBlock.createWithTxStatus(depositInvalid.timestamp, Seq(depositInvalid), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + } + } } \ No newline at end of file From 179c4f22734597d013006629c42662c40cc201ba Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 29 Jun 2021 15:59:38 +0800 Subject: [PATCH 344/391] Fix the withdraw of blacklist in ContractNonFungibleV2 and add withdraw invalid test --- .../contract/ContractNonFungibleV2.scala | 2 +- ...NonFungibleContractV2InvalidDiffTest.scala | 145 +++++++++++++++++- 2 files changed, 144 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala index b7cb97d1e..d4645fa55 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractNonFungibleV2.scala @@ -191,7 +191,7 @@ object ContractNonFungibleV2 { val withdrawBlacklistOpcs: Seq[Array[Byte]] = Seq( assertCaller ++ Array(1.toByte), basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(3.toByte) - ) ++ whitelistCheck(0.toByte, 1.toByte) ++ Seq( + ) ++ blacklistCheck(0.toByte, 1.toByte) ++ Seq( tdbaTransfer ++ Array(0.toByte, 1.toByte, 3.toByte, 2.toByte) ) lazy val withdrawBlacklistFunc: Array[Byte] = getFunctionBytes(withdrawId, publicFuncType, nonReturnType, withdrawDataType, withdrawBlacklistOpcs) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala index 072aaae4e..665456b9e 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala @@ -495,7 +495,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Success)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success } - // only update depositor to whitelist before withdraw + // only update depositor to whitelist assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1))), TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Failed)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed @@ -505,11 +505,152 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Failed)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed } - // withdraw with a wrong caller + // deposit with a wrong caller assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2))), TestBlock.createWithTxStatus(depositInvalid.timestamp, Seq(depositInvalid), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller } } } + val preconditionsNonFungibleBlackContractV2WithdrawInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractBlack <- nonFungibleBlackContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractBlack <- registerNonFungibleV2Gen(master, contractBlack, dataStack, description, fee + 10000000000L, ts) + contractBlackId = regContractBlack.contractId + tokenId = tokenIdFromBytes(contractBlackId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + contractLock <- lockContractGen + dataStack: Seq[DataEntry] <- initLockContractDataStackGen(tokenId.arr) + description <- validDescStringGen + regContractLock <- registerLockGen(master, contractLock, dataStack, description, fee + 10000000000L, ts) + contractLockId = regContractLock.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractBlackId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + deposit <- depositNonFungibleV2Gen(master, contractBlackId, depositData, depositType, attach, fee, ts) + + withdrawData = Seq(contractLockId.bytes.arr, master.toAddress.bytes.arr, Ints.toByteArray(0)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Int32) + withdraw <- withdrawNonFungibleV2Gen(master, contractBlackId, withdrawData, withdrawType, attach, fee, ts) + + withdrawData = Seq(contractLockId.bytes.arr, user.toAddress.bytes.arr, Ints.toByteArray(0)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Int32) + withdrawInvalid <- withdrawNonFungibleV2Gen(master, contractBlackId, withdrawData, withdrawType, attach, fee, ts) + + } yield (genesis, genesis2, regContractBlack, regContractLock, issue, updateList1, deposit, withdraw, withdrawInvalid) + + property("Execute withdraw in non fungible black contract") { + forAll(preconditionsNonFungibleBlackContractV2WithdrawInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, regContractLock: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction, withdrawInvalid: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue, deposit))), + TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + // update blacklist before withdraw + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue, deposit, updateList1))), + TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // withdraw with a wrong caller + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue, deposit))), + TestBlock.createWithTxStatus(withdrawInvalid.timestamp, Seq(withdrawInvalid), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + + } + } + + val preconditionsNonFungibleWhiteContractV2WithdrawInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractWhite <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractWhiteId = regContractWhite.contractId + tokenId = tokenIdFromBytes(contractWhiteId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + contractLock <- lockContractGen + dataStack: Seq[DataEntry] <- initLockContractDataStackGen(tokenId.arr) + description <- validDescStringGen + regContractLock <- registerLockGen(master, contractLock, dataStack, description, fee + 10000000000L, ts) + contractLockId = regContractLock.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractWhiteId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + deposit <- depositNonFungibleV2Gen(master, contractWhiteId, depositData, depositType, attach, fee, ts) + + withdrawData = Seq(contractLockId.bytes.arr, master.toAddress.bytes.arr, Ints.toByteArray(0)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Int32) + withdraw <- withdrawNonFungibleV2Gen(master, contractWhiteId, withdrawData, withdrawType, attach, fee, ts) + + withdrawData = Seq(contractLockId.bytes.arr, user.toAddress.bytes.arr, Ints.toByteArray(0)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Int32) + withdrawInvalid <- withdrawNonFungibleV2Gen(master, contractWhiteId, withdrawData, withdrawType, attach, fee, ts) + + } yield (genesis, genesis2, regContractWhite, regContractLock, issue, updateList1, updateList2, updateList3, updateList4, deposit, withdraw, withdrawInvalid) + + property("Execute withdraw in non fungible white contract") { + forAll(preconditionsNonFungibleWhiteContractV2WithdrawInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, regContractLock: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction, withdrawInvalid: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2, deposit))), + TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + // only update depositor to whitelist before withdraw + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2, deposit, updateList3))), + TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // only update contract to whitelist before withdraw + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2, deposit, updateList4))), + TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // withdraw with a wrong caller + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2, deposit))), + TestBlock.createWithTxStatus(withdrawInvalid.timestamp, Seq(withdrawInvalid), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller + } + } + } } \ No newline at end of file From 2cad133179db433f69f142ce2f6a1a910659cb95 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 15:59:44 +0800 Subject: [PATCH 345/391] Add judge cancel function to contract OPC --- src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala index ae60d9d8f..bd20aafa9 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVEscrow.scala @@ -8,7 +8,7 @@ import vsys.utils.serialization.Deser object ContractVEscrow { lazy val contract: Contract = Contract.buildContract(Deser.serilizeString("vdds"), Ints.toByteArray(2), Seq(initTrigger, depositTrigger, withdrawTrigger), // Triggers - Seq(supersedeFunc, createFunc, recipientDepositFunc, judgeDepositFunc, payerCancelFunc, recipientCancelFunc, + Seq(supersedeFunc, createFunc, recipientDepositFunc, judgeDepositFunc, payerCancelFunc, recipientCancelFunc, judgeCancelFunc, submitWorkFunc, approveWorkFunc, applyToJudgeFunc, judgeFunc, submitPenaltyFunc, payerRefundFunc, recipientRefundFunc, collectFunc), stateVarSeq, // StateVars @@ -467,7 +467,7 @@ object ContractVEscrow { cdbvrMapGet ++ Array(orderJudgeStatusMap.index, 0.toByte, 5.toByte), assertEqual ++ Array(4.toByte, 5.toByte)) ++ timestampCheck(6, false) ++ Seq( cdbvrGet ++ Array(judgeStateVar.index, 9.toByte), - cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 10.toByte), + cdbvrMapGet ++ Array(orderRecipientAmountMap.index, 0.toByte, 10.toByte), cdbvrMapGet ++ Array(orderRepLockedAmountMap.index, 0.toByte, 11.toByte), basicAdd ++ Array(10.toByte, 11.toByte, 12.toByte), cdbvMapValAdd ++ Array(contractBalanceMap.index, 1.toByte, 12.toByte), From 6554d9f66ba828b4586b5dd636546fa77992368b Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 16:03:20 +0800 Subject: [PATCH 346/391] Add basic v escrow function tests --- .../ExecuteVEscrowContractValidDiffTest.scala | 252 ++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractValidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractValidDiffTest.scala new file mode 100644 index 000000000..a937f41ce --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractValidDiffTest.scala @@ -0,0 +1,252 @@ +package vsys.blockchain.state.contract.vescrow + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract._ +import vsys.blockchain.contract.token.SystemContractGen +import vsys.blockchain.contract.vescrow.VEscrowContractGen +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.contract._ +import vsys.blockchain.state._ +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import com.google.common.primitives.{Ints, Longs} +import vsys.account.ContractAccount +import vsys.account.ContractAccount.tokenIdFromBytes + +class ExecuteVEscrowContractValidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with SystemContractGen + with VEscrowContractGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndExecuteContractEscrow: Gen[(GenesisTransaction, GenesisTransaction, GenesisTransaction, + RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (judge, ts, fee) <- ContractGenHelper.basicContractTestGen() + recipient <- accountGen + payer <- accountGen + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + genesis <- genesisVEscrowGen(judge, ts) + genesis2 <- genesisVEscrowGen(recipient, ts) + genesis3 <- genesisVEscrowGen(payer, ts) + vEscrow <- vEscrowContractGen() + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + initVEscrowDataStack <- initVEscrowDataStackGen(tokenId.arr, 1000000000L, 1000000000L) + regVEscrow <- registerVEscrowGen(judge, vEscrow, initVEscrowDataStack, "test", fee, ts) + judgeDepositVSYSData = Seq(judge.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + recipientDepositVSYSData = Seq(recipient.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + payerDepositVSYSData = Seq(payer.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + depositVSYSDataType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + judgeDepositVSYS <- depositVSYSGen(judge, judgeDepositVSYSData, depositVSYSDataType, attach, fee, ts + 1) + recipientDepositVSYS <- depositVSYSGen(recipient, recipientDepositVSYSData, depositVSYSDataType, attach, fee, ts + 2) + payerDepositVSYS <- depositVSYSGen(payer, payerDepositVSYSData, depositVSYSDataType, attach, fee, ts + 3) + withdrawVSYSData = Seq(regVEscrow.contractId.bytes.arr, judge.toAddress.bytes.arr, Longs.toByteArray(100000L)) + withdrawVSYSDataType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + judgeWithdrawVSYS <- withdrawVSYSGen(judge, withdrawVSYSData, withdrawVSYSDataType, attach, fee, ts + 4) + createVEscrow <- createVEscrowGen(payer, regVEscrow.contractId, recipient.toAddress, 1000L, 1000L, 1000L, 10L, 10L, ts + 100L, attach, fee, ts + 5) + recipientDepositToOrder <- recipientDepositVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 6) + judgeDepositToOrder <- judgeDepositVEscrowGen(judge, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 7) + payerCancelOrder <- payerCancelVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 8) + recipientCancelOrder <- recipientCancelVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 10) + judgeCancelOrder <- judgeCancelVEscrowGen(judge, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 11) + submitWork <- submitWorkVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 12) + approveWork <- approveWorkVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 13) + applyToJudge <- applyToJudgeVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach,fee, ts + 14) + judgeWork <- judgeVEscrowGen(judge, regVEscrow.contractId, createVEscrow.id.arr,0L, 1990L, attach, fee, ts + 15) + submitPenalty <- submitPenaltyVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 16) + payerRefund <- payerRefundVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 17) + recipientRefund <- recipientRefundVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 18) + recipientCollect <- collectVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 19) + } yield (genesis, genesis2, genesis3, regVEscrow, judgeDepositVSYS, recipientDepositVSYS, payerDepositVSYS, judgeWithdrawVSYS, + createVEscrow, recipientDepositToOrder, judgeDepositToOrder, payerCancelOrder, recipientCancelOrder, judgeCancelOrder, submitWork, approveWork, + applyToJudge, judgeWork, submitPenalty, payerRefund, recipientRefund, recipientCollect) + + property("v-escrow able to deposit and withdraw VSYS") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, _, _, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, _, _, judgeWithdrawVSYS: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, + _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS))), + TestBlock.createWithTxStatus(judgeWithdrawVSYS.timestamp, Seq(judgeWithdrawVSYS), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow able to register and create") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, _, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, _, + _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS))), + TestBlock.createWithTxStatus(createVEscrow.timestamp, Seq(createVEscrow), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow able to deposit to order") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, _, _, _, _, + _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(recipientDepositToOrder.timestamp, Seq(recipientDepositToOrder, judgeDepositToOrder), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow payer able to cancel order") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, judgeDepositToOrder: ExecuteContractFunctionTransaction, payerCancelOrder: ExecuteContractFunctionTransaction, _, _, _, _, + _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, judgeDepositToOrder))), + TestBlock.createWithTxStatus(payerCancelOrder.timestamp, Seq(payerCancelOrder), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow recipient able to cancel order") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, recipientCancelOrder: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, judgeDepositToOrder))), + TestBlock.createWithTxStatus(recipientCancelOrder.timestamp, Seq(recipientCancelOrder), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow judge able to cancel order") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, _, + _, _, judgeCancelOrder: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder))), + TestBlock.createWithTxStatus(judgeCancelOrder.timestamp, Seq(judgeCancelOrder), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow recipient able to submit work") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, submitWork: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder))), + TestBlock.createWithTxStatus(submitWork.timestamp, Seq(submitWork), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow payer able to approve work") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, submitWork: ExecuteContractFunctionTransaction, approveWork: ExecuteContractFunctionTransaction, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork))), + TestBlock.createWithTxStatus(approveWork.timestamp, Seq(approveWork), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow payer able to apply to judge") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, submitWork: ExecuteContractFunctionTransaction, _, applyToJudge: ExecuteContractFunctionTransaction, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork))), + TestBlock.createWithTxStatus(applyToJudge.timestamp, Seq(applyToJudge), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow judge able to judge work") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, submitWork: ExecuteContractFunctionTransaction, _, applyToJudge: ExecuteContractFunctionTransaction, judgeWork: ExecuteContractFunctionTransaction, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork, applyToJudge))), + TestBlock.createWithTxStatus(judgeWork.timestamp, Seq(judgeWork), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow payer able to submit penalty") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, _, _, _, _, submitPenalty: ExecuteContractFunctionTransaction, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder))), + TestBlock.createWithTxStatus(submitPenalty.timestamp + 1000000000L, Seq(submitPenalty), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow payer able to refund") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, submitWork: ExecuteContractFunctionTransaction, _, applyToJudge: ExecuteContractFunctionTransaction, _, _, payerRefund: ExecuteContractFunctionTransaction, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(applyToJudge.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork, applyToJudge))), + TestBlock.createWithTxStatus(payerRefund.timestamp + 1000000000L, Seq(payerRefund), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow recipient able to refund") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, submitWork: ExecuteContractFunctionTransaction, _, applyToJudge: ExecuteContractFunctionTransaction, _, _, _, + recipientRefund: ExecuteContractFunctionTransaction, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(applyToJudge.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork, applyToJudge))), + TestBlock.createWithTxStatus(recipientRefund.timestamp + 1000000000L, Seq(recipientRefund), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + property("v-escrow recipient able to collect") { + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, submitWork: ExecuteContractFunctionTransaction, _, _, _, _, _, _, recipientCollect: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork))), + TestBlock.createWithTxStatus(recipientCollect.timestamp + 1000000000L, Seq(recipientCollect), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } +} \ No newline at end of file From 4a007fa11cb9871c52ff13235134811d84c5a12d Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 16:09:15 +0800 Subject: [PATCH 347/391] Add tests for basic invalid cases for v escrow --- ...xecuteVEscrowContractInvalidDiffTest.scala | 485 ++++++++++++++++++ 1 file changed, 485 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractInvalidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractInvalidDiffTest.scala new file mode 100644 index 000000000..736fa784f --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractInvalidDiffTest.scala @@ -0,0 +1,485 @@ +package vsys.blockchain.state.contract.vescrow + +import org.scalacheck.{Gen, Shrink} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import org.scalatest.{Matchers, PropSpec} +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract._ +import vsys.blockchain.contract.token.SystemContractGen +import vsys.blockchain.contract.vescrow.VEscrowContractGen +import vsys.blockchain.state.diffs._ +import vsys.blockchain.transaction.contract._ +import vsys.blockchain.state._ +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import com.google.common.primitives.{Ints, Longs} +import vsys.account.ContractAccount +import vsys.account.ContractAccount.tokenIdFromBytes + +class ExecuteVEscrowContractInvalidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with SystemContractGen + with VEscrowContractGen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val preconditionsAndVEscrowInvalidDeposits: Gen[(GenesisTransaction, GenesisTransaction, GenesisTransaction, + RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (judge, ts, fee) <- ContractGenHelper.basicContractTestGen() + recipient <- accountGen + payer <- accountGen + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + genesis <- genesisVEscrowGen(judge, ts) + genesis2 <- genesisVEscrowGen(recipient, ts) + genesis3 <- genesisVEscrowGen(payer, ts) + vEscrow <- vEscrowContractGen() + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + initVEscrowDataStack <- initVEscrowDataStackGen(tokenId.arr, 1000000000L, 1000000000L) + regVEscrow <- registerVEscrowGen(judge, vEscrow, initVEscrowDataStack, "test", fee, ts) + + judgeDepositVSYSData = Seq(judge.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + recipientDepositVSYSData = Seq(recipient.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + payerDepositVSYSData = Seq(payer.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + depositVSYSDataType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + judgeDepositVSYS <- depositVSYSGen(judge, judgeDepositVSYSData, depositVSYSDataType, attach, fee, ts + 1) + recipientDepositVSYS <- depositVSYSGen(recipient, recipientDepositVSYSData, depositVSYSDataType, attach, fee, ts + 2) + payerDepositVSYS <- depositVSYSGen(payer, payerDepositVSYSData, depositVSYSDataType, attach, fee, ts + 3) + + withdrawVSYSData = Seq(regVEscrow.contractId.bytes.arr, judge.toAddress.bytes.arr, Longs.toByteArray(1000000000001L)) + withdrawVSYSDataType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) + judgeWithdrawVSYS <- withdrawVSYSGen(judge, withdrawVSYSData, withdrawVSYSDataType, attach, fee, ts + 4) + + createVEscrow <- createVEscrowGen(payer, regVEscrow.contractId, recipient.toAddress, 1000L, 1000L, 1000L, 10L, 10L, ts + 100L, attach, fee, ts + 5) + createVEscrowLargeDepositAmounts <- createVEscrowGen(payer, regVEscrow.contractId, recipient.toAddress, 1000L, 1000000000001L, 1000000000001L, 10L, 10L, ts + 100L, attach, fee, ts + 5) + invalidCreateVEscrowLargeCreateAmount <- createVEscrowGen(payer, regVEscrow.contractId, recipient.toAddress, 1000000000001L, 1000L, 1000L, 10L, 10L, ts + 100L, attach, fee, ts + 5) + + recipientDepositToOrder <- recipientDepositVEscrowGen(recipient, regVEscrow.contractId, createVEscrowLargeDepositAmounts.id.arr, attach, fee, ts + 6) + judgeDepositToOrder <- judgeDepositVEscrowGen(judge, regVEscrow.contractId, createVEscrowLargeDepositAmounts.id.arr, attach, fee, ts + 7) + + recipientSubmitWork <- submitWorkVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 8) + + payerSubmitPenalty <- submitPenaltyVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 9) + + approveWork <- approveWorkVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 10) + + applyToJudge <- applyToJudgeVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 11) + + recipientCollect <- collectVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 12) + + judgeOrder <- judgeVEscrowGen(judge, regVEscrow.contractId, createVEscrow.id.arr, 100, 100, attach, fee, ts + 13) + + payerRefundOrder <- payerRefundVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 14) + + recipientRefundOrder <- recipientRefundVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 15) + + } yield (genesis, genesis2, genesis3, regVEscrow, judgeDepositVSYS, recipientDepositVSYS, payerDepositVSYS, judgeWithdrawVSYS, createVEscrow, createVEscrowLargeDepositAmounts, invalidCreateVEscrowLargeCreateAmount, + recipientDepositToOrder, judgeDepositToOrder, recipientSubmitWork, payerSubmitPenalty, approveWork, applyToJudge, recipientCollect, judgeOrder, payerRefundOrder, recipientRefundOrder) + + property("v-escrow unable to withdraw more than deposited") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, _, _, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, _, _, judgeWithdrawVSYS: ExecuteContractFunctionTransaction, _, _, _, + _, _, _, _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS))), + TestBlock.createWithTxStatus(judgeWithdrawVSYS.timestamp, Seq(judgeWithdrawVSYS), TransactionStatus.ContractTokenBalanceInsufficient)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractTokenBalanceInsufficient + } + } + } + + property("v-escrow unable to create without sufficient amount") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, _, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, _, _, _, invalidCreateVEscrow: ExecuteContractFunctionTransaction, + _, _, _, _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS))), + TestBlock.createWithTxStatus(invalidCreateVEscrow.timestamp, Seq(invalidCreateVEscrow), TransactionStatus.ContractMapValueInsufficient)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + } + } + + property("v-escrow recipient unable to deposit without sufficient amount") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, _, createVEscrowLargeDepositAmounts: ExecuteContractFunctionTransaction, _, recipientDepositToOrder: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrowLargeDepositAmounts))), + TestBlock.createWithTxStatus(recipientDepositToOrder.timestamp, Seq(recipientDepositToOrder), TransactionStatus.ContractMapValueInsufficient)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + } + } + + property("v-escrow judge unable to deposit without sufficient amount") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, _, createVEscrowLargeDepositAmounts: ExecuteContractFunctionTransaction, _, _, judgeDepositToOrder: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrowLargeDepositAmounts))), + TestBlock.createWithTxStatus(judgeDepositToOrder.timestamp, Seq(judgeDepositToOrder), TransactionStatus.ContractMapValueInsufficient)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractMapValueInsufficient + } + } + } + + property("v-escrow recipient unable to submit before judge deposits") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, recipientSubmitWork: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(recipientSubmitWork.timestamp, Seq(recipientSubmitWork), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer unable to submit penalty before order deposits") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, payerSubmitPenalty: ExecuteContractFunctionTransaction, _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(payerSubmitPenalty.timestamp, Seq(payerSubmitPenalty), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer unable to approve before order deposits") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, _, approveWork: ExecuteContractFunctionTransaction, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(approveWork.timestamp, Seq(approveWork), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer unable to apply to judge before order deposits") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, applyToJudge: ExecuteContractFunctionTransaction, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(applyToJudge.timestamp, Seq(applyToJudge), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow recipient cannot collect before order deposits") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _, recipientCollect: ExecuteContractFunctionTransaction, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(recipientCollect.timestamp, Seq(recipientCollect), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow cannnot judge before order deposits") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _, _, judgeOrder: ExecuteContractFunctionTransaction, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(judgeOrder.timestamp, Seq(judgeOrder), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer cannot refund before order deposits") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _, _, _, payerRefundOrder: ExecuteContractFunctionTransaction, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(payerRefundOrder.timestamp, Seq(payerRefundOrder), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow recipient cannot refund before order deposits") { + forAll(preconditionsAndVEscrowInvalidDeposits) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, + _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _, _, _, _, recipientRefundOrder: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, createVEscrow))), + TestBlock.createWithTxStatus(recipientRefundOrder.timestamp, Seq(recipientRefundOrder), TransactionStatus.Failed)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsAndVEscrowInvalidSubmit: Gen[(GenesisTransaction, GenesisTransaction, GenesisTransaction, + RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction)] = for { + (judge, ts, fee) <- ContractGenHelper.basicContractTestGen() + recipient <- accountGen + payer <- accountGen + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + genesis <- genesisVEscrowGen(judge, ts) + genesis2 <- genesisVEscrowGen(recipient, ts) + genesis3 <- genesisVEscrowGen(payer, ts) + vEscrow <- vEscrowContractGen() + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + initVEscrowDataStack <- initVEscrowDataStackGen(tokenId.arr, 1000000000L, 1000000000L) + regVEscrow <- registerVEscrowGen(judge, vEscrow, initVEscrowDataStack, "test", fee, ts) + + judgeDepositVSYSData = Seq(judge.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + recipientDepositVSYSData = Seq(recipient.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + payerDepositVSYSData = Seq(payer.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + depositVSYSDataType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + judgeDepositVSYS <- depositVSYSGen(judge, judgeDepositVSYSData, depositVSYSDataType, attach, fee, ts + 1) + recipientDepositVSYS <- depositVSYSGen(recipient, recipientDepositVSYSData, depositVSYSDataType, attach, fee, ts + 2) + payerDepositVSYS <- depositVSYSGen(payer, payerDepositVSYSData, depositVSYSDataType, attach, fee, ts + 3) + + createVEscrow <- createVEscrowGen(payer, regVEscrow.contractId, recipient.toAddress, 1000L, 1000L, 1000L, 10L, 10L, ts + 100L, attach, fee, ts + 4) + + recipientDepositToOrder <- recipientDepositVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 5) + judgeDepositToOrder <- judgeDepositVEscrowGen(judge, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 6) + + approveWork <- approveWorkVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 7) + + applyToJudge <- applyToJudgeVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 8) + + recipientCollect <- collectVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 9) + + judgeOrder <- judgeVEscrowGen(judge, regVEscrow.contractId, createVEscrow.id.arr, 100, 100, attach, fee, ts + 10) + + payerRefundOrder <- payerRefundVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 11) + + recipientRefundOrder <- recipientRefundVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 12) + + } yield (genesis, genesis2, genesis3, regVEscrow, judgeDepositVSYS, recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, + approveWork, applyToJudge, recipientCollect, judgeOrder, payerRefundOrder, recipientRefundOrder) + + property("v-escrow judge cannot approve work before recipient submits work") { + forAll(preconditionsAndVEscrowInvalidSubmit) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + approveWork: ExecuteContractFunctionTransaction, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, recipientDepositVSYS, createVEscrow, + recipientDepositToOrder, judgeDepositToOrder))), + TestBlock.createWithTxStatus(approveWork.timestamp, Seq(approveWork), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer cannot apply to judge before recipient submits work") { + forAll(preconditionsAndVEscrowInvalidSubmit) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, applyToJudge: ExecuteContractFunctionTransaction, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, recipientDepositVSYS, createVEscrow, + recipientDepositToOrder, judgeDepositToOrder))), + TestBlock.createWithTxStatus(applyToJudge.timestamp, Seq(applyToJudge), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow recipient cannot collect before recipient submits work") { + forAll(preconditionsAndVEscrowInvalidSubmit) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, recipientCollect: ExecuteContractFunctionTransaction, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, recipientDepositVSYS, createVEscrow, + recipientDepositToOrder, judgeDepositToOrder))), + TestBlock.createWithTxStatus(recipientCollect.timestamp, Seq(recipientCollect), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow judge cannot judge order before recipient submits work") { + forAll(preconditionsAndVEscrowInvalidSubmit) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, judgeOrder: ExecuteContractFunctionTransaction, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, recipientDepositVSYS, createVEscrow, + recipientDepositToOrder, judgeDepositToOrder))), + TestBlock.createWithTxStatus(judgeOrder.timestamp, Seq(judgeOrder), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer cannot refund order before recipient submits work") { + forAll(preconditionsAndVEscrowInvalidSubmit) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, _, payerRefundOrder: ExecuteContractFunctionTransaction, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, recipientDepositVSYS, createVEscrow, + recipientDepositToOrder, judgeDepositToOrder))), + TestBlock.createWithTxStatus(payerRefundOrder.timestamp, Seq(payerRefundOrder), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow recipient cannot refund order before recipient submits work") { + forAll(preconditionsAndVEscrowInvalidSubmit) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, + createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, + _, _, _, _, _, recipientRefundOrder: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS, recipientDepositVSYS, createVEscrow, + recipientDepositToOrder, judgeDepositToOrder))), + TestBlock.createWithTxStatus(recipientRefundOrder.timestamp, Seq(recipientRefundOrder), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + val preconditionsAndVEscrowInvalidTimestamps: Gen[(GenesisTransaction, GenesisTransaction, GenesisTransaction, + RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (judge, ts, fee) <- ContractGenHelper.basicContractTestGen() + recipient <- accountGen + payer <- accountGen + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + genesis <- genesisVEscrowGen(judge, ts) + genesis2 <- genesisVEscrowGen(recipient, ts) + genesis3 <- genesisVEscrowGen(payer, ts) + vEscrow <- vEscrowContractGen() + tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + initVEscrowDataStack <- initVEscrowDataStackGen(tokenId.arr, 1000000000L, 1000000000L) + regVEscrow <- registerVEscrowGen(judge, vEscrow, initVEscrowDataStack, "test", fee, ts) + + judgeDepositVSYSData = Seq(judge.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + recipientDepositVSYSData = Seq(recipient.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + payerDepositVSYSData = Seq(payer.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + depositVSYSDataType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) + judgeDepositVSYS <- depositVSYSGen(judge, judgeDepositVSYSData, depositVSYSDataType, attach, fee, ts + 1) + recipientDepositVSYS <- depositVSYSGen(recipient, recipientDepositVSYSData, depositVSYSDataType, attach, fee, ts + 2) + payerDepositVSYS <- depositVSYSGen(payer, payerDepositVSYSData, depositVSYSDataType, attach, fee, ts + 3) + + createVEscrow <- createVEscrowGen(payer, regVEscrow.contractId, recipient.toAddress, 1000L, 1000L, 1000L, 10L, 10L, ts + 100L, attach, fee, ts + 5) + + recipientDepositToOrder <- recipientDepositVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 6) + judgeDepositToOrder <- judgeDepositVEscrowGen(judge, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 7) + + recipientSubmitWork <- submitWorkVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 8) + + payerSubmitPenalty <- submitPenaltyVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 9) + + approveWork <- approveWorkVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 10) + + applyToJudge <- applyToJudgeVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 11) + + recipientCollect <- collectVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 12) + + judgeOrder <- judgeVEscrowGen(judge, regVEscrow.contractId, createVEscrow.id.arr, 100, 100, attach, fee, ts + 13) + + payerRefundOrder <- payerRefundVEscrowGen(payer, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 14) + + recipientRefundOrder <- recipientRefundVEscrowGen(recipient, regVEscrow.contractId, createVEscrow.id.arr, attach, fee, ts + 15) + + } yield (genesis, genesis2, genesis3, regVEscrow, judgeDepositVSYS, recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, + judgeDepositToOrder, recipientSubmitWork, payerSubmitPenalty, approveWork, applyToJudge, recipientCollect, judgeOrder, payerRefundOrder, recipientRefundOrder) + + property("v-escrow payer cannot submit penalty before the order expires") { + forAll(preconditionsAndVEscrowInvalidTimestamps) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, + payerDepositVSYS: ExecuteContractFunctionTransaction, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, + judgeDepositToOrder: ExecuteContractFunctionTransaction, recipientSubmitWork: ExecuteContractFunctionTransaction, payerSubmitPenalty: ExecuteContractFunctionTransaction, + _, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, + payerDepositVSYS, recipientDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, recipientSubmitWork))), + TestBlock.createWithTxStatus(payerSubmitPenalty.timestamp, Seq(payerSubmitPenalty), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer cannot approve the order after it expires") { + forAll(preconditionsAndVEscrowInvalidTimestamps) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, + payerDepositVSYS: ExecuteContractFunctionTransaction, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, + judgeDepositToOrder: ExecuteContractFunctionTransaction, recipientSubmitWork: ExecuteContractFunctionTransaction, _, + approveWork: ExecuteContractFunctionTransaction, _, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientSubmitWork.timestamp, Seq(regVEscrow, judgeDepositVSYS, + payerDepositVSYS, recipientDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, recipientSubmitWork))), + TestBlock.createWithTxStatus(approveWork.timestamp + 1000000000L, Seq(approveWork), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer cannot apply to judge once order expires") { + forAll(preconditionsAndVEscrowInvalidTimestamps) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, + payerDepositVSYS: ExecuteContractFunctionTransaction, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, + judgeDepositToOrder: ExecuteContractFunctionTransaction, recipientSubmitWork: ExecuteContractFunctionTransaction, _, + _, applyToJudge: ExecuteContractFunctionTransaction, _, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientSubmitWork.timestamp, Seq(regVEscrow, judgeDepositVSYS, + payerDepositVSYS, recipientDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, recipientSubmitWork))), + TestBlock.createWithTxStatus(applyToJudge.timestamp + 1000000000L, Seq(applyToJudge), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow recipient cannot collect before order expires") { + forAll(preconditionsAndVEscrowInvalidTimestamps) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, + payerDepositVSYS: ExecuteContractFunctionTransaction, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, + judgeDepositToOrder: ExecuteContractFunctionTransaction, recipientSubmitWork: ExecuteContractFunctionTransaction, _, + _, _, recipientCollect: ExecuteContractFunctionTransaction, _, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientSubmitWork.timestamp, Seq(regVEscrow, judgeDepositVSYS, + payerDepositVSYS, recipientDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, recipientSubmitWork))), + TestBlock.createWithTxStatus(recipientCollect.timestamp, Seq(recipientCollect), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow judge cannot judge order after it expires") { + forAll(preconditionsAndVEscrowInvalidTimestamps) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, + payerDepositVSYS: ExecuteContractFunctionTransaction, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, + judgeDepositToOrder: ExecuteContractFunctionTransaction, recipientSubmitWork: ExecuteContractFunctionTransaction, _, + _, _, _, judgeOrder: ExecuteContractFunctionTransaction, _, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientSubmitWork.timestamp, Seq(regVEscrow, judgeDepositVSYS, + payerDepositVSYS, recipientDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, recipientSubmitWork))), + TestBlock.createWithTxStatus(judgeOrder.timestamp, Seq(judgeOrder), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow payer cannot refund order before it expires") { + forAll(preconditionsAndVEscrowInvalidTimestamps) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, + payerDepositVSYS: ExecuteContractFunctionTransaction, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, + judgeDepositToOrder: ExecuteContractFunctionTransaction, recipientSubmitWork: ExecuteContractFunctionTransaction, _, + _, _, _, _, payerRefundOrder: ExecuteContractFunctionTransaction, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientSubmitWork.timestamp, Seq(regVEscrow, judgeDepositVSYS, + payerDepositVSYS, recipientDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, recipientSubmitWork))), + TestBlock.createWithTxStatus(payerRefundOrder.timestamp, Seq(payerRefundOrder), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } + + property("v-escrow recipient cannot refund order before it expires") { + forAll(preconditionsAndVEscrowInvalidTimestamps) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, + regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, + payerDepositVSYS: ExecuteContractFunctionTransaction, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, + judgeDepositToOrder: ExecuteContractFunctionTransaction, recipientSubmitWork: ExecuteContractFunctionTransaction, _, + _, _, _, _, _, recipientRefundOrder: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientSubmitWork.timestamp, Seq(regVEscrow, judgeDepositVSYS, + payerDepositVSYS, recipientDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, recipientSubmitWork))), + TestBlock.createWithTxStatus(recipientRefundOrder.timestamp, Seq(recipientRefundOrder), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + } + } +} \ No newline at end of file From f8a433b790a96935b791a4a73d22b2aff0f278dc Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 29 Jun 2021 16:09:57 +0800 Subject: [PATCH 348/391] Update state check in ExecuteNonFungibleContractV2ValidDiffTest --- ...NonFungibleContractV2InvalidDiffTest.scala | 30 +- ...teNonFungibleContractV2ValidDiffTest.scala | 615 ++++++++++++++++++ 2 files changed, 636 insertions(+), 9 deletions(-) create mode 100644 src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2ValidDiffTest.scala diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala index 665456b9e..466581b59 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2InvalidDiffTest.scala @@ -65,6 +65,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(updateList2.timestamp, Seq(updateList2), TransactionStatus.Success)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success } + // update list not with a NFT contract owner assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(reg.timestamp, Seq(reg, issue))), TestBlock.createWithTxStatus(updateList3.timestamp, Seq(updateList3), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller @@ -414,13 +415,13 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success } - // depositor on black list + // master depositor on black list assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractBlack, regContractLock, issue, updateList1))), TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Failed)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed } - // depositor on black list + // user depositor try to deposit assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList1.timestamp, Seq(regContractBlack, regContractLock, issue, updateList1))), TestBlock.createWithTxStatus(depositInvalid.timestamp, Seq(depositInvalid), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.ContractInvalidCaller @@ -495,12 +496,12 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Success)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success } - // only update depositor to whitelist + // only update master depositor to whitelist assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1))), TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Failed)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed } - // only update contract to whitelist before withdraw + // only update contract to whitelist assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList2))), TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Failed)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed @@ -513,7 +514,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec } } val preconditionsNonFungibleBlackContractV2WithdrawInvalidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, - ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { (master, ts, fee) <- ContractGenHelper.basicContractTestGen() contractBlack <- nonFungibleBlackContract user <- accountGen @@ -540,6 +541,10 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec updateListType = Seq(DataType.Address, DataType.Boolean) updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + updateListData = Seq(contractLockId.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) deposit <- depositNonFungibleV2Gen(master, contractBlackId, depositData, depositType, attach, fee, ts) @@ -552,20 +557,27 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Int32) withdrawInvalid <- withdrawNonFungibleV2Gen(master, contractBlackId, withdrawData, withdrawType, attach, fee, ts) - } yield (genesis, genesis2, regContractBlack, regContractLock, issue, updateList1, deposit, withdraw, withdrawInvalid) + } yield (genesis, genesis2, regContractBlack, regContractLock, issue, updateList1, updateList2, deposit, withdraw, withdrawInvalid) property("Execute withdraw in non fungible black contract") { forAll(preconditionsNonFungibleBlackContractV2WithdrawInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, regContractLock: RegisterContractTransaction, - issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction, withdrawInvalid: ExecuteContractFunctionTransaction) => + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction, withdrawInvalid: ExecuteContractFunctionTransaction) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue, deposit))), TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Success)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success } - // update blacklist before withdraw + // update master withdrawer into blacklist before withdraw assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue, deposit, updateList1))), TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Failed)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed } + + // update contract into blacklist before withdraw + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue, deposit, updateList2))), + TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Failed)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed + } + // withdraw with a wrong caller assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue, deposit))), TestBlock.createWithTxStatus(withdrawInvalid.timestamp, Seq(withdrawInvalid), TransactionStatus.ContractInvalidCaller)) { (blockDiff, _) => @@ -636,7 +648,7 @@ class ExecuteNonFungibleContractV2InvalidDiffTest extends PropSpec TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Success)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success } - // only update depositor to whitelist before withdraw + // only update withdrawer to whitelist before withdraw assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2, deposit, updateList3))), TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Failed)) { (blockDiff, _) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Failed diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2ValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2ValidDiffTest.scala new file mode 100644 index 000000000..526013b08 --- /dev/null +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2ValidDiffTest.scala @@ -0,0 +1,615 @@ +package vsys.blockchain.state.contract.token + +import cats.Monoid +import vsys.blockchain.state._ +import com.google.common.primitives.{Bytes, Ints, Shorts} +import org.scalacheck.{Gen, Shrink} +import org.scalatest.{Matchers, PropSpec} +import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} +import vsys.account.ContractAccount.tokenIdFromBytes +import vsys.blockchain.block.TestBlock +import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry, DataType} +import vsys.blockchain.contract.ContractGenHelper.{feeScale, genBoundedString} +import vsys.blockchain.contract.lock.LockContractGen +import vsys.blockchain.contract.token.NonFungibleContractV2Gen +import vsys.blockchain.state.ByteStr +import vsys.blockchain.state.diffs.assertDiffAndStateCorrectBlockTime +import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} +import vsys.blockchain.transaction.contract.{ExecuteContractFunctionTransaction, RegisterContractTransaction} + +class ExecuteNonFungibleContractV2ValidDiffTest extends PropSpec + with PropertyChecks + with GeneratorDrivenPropertyChecks + with Matchers + with TransactionGen + with LockContractGen + with NonFungibleContractV2Gen { + + private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) + + val nonFungibleWhiteContract: Gen[Contract] = nonFungibleContractWhiteGen() + val nonFungibleBlackContract: Gen[Contract] = nonFungibleContractBlackGen() + + val preconditionsNonFungibleContractV2IssueValidTest: Gen[(GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContract <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisNonFungibleV2Gen(master, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractId, issueData, attach, fee, ts+1) + } yield (genesis, regContract, issue) + + property("Execute issue with non fungible contract V2") { + forAll(preconditionsNonFungibleContractV2IssueValidTest) { case (genesis: GenesisTransaction, reg: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(reg.timestamp, Seq(reg))), + TestBlock.createWithTxStatus(issue.timestamp, Seq(issue), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = reg.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val maker = reg.proofs.firstCurveProof.explicitGet().publicKey + val issuer = issue.proofs.firstCurveProof.explicitGet().publicKey + + //Statevar keys + val issuerBalanceKey = ByteStr(Bytes.concat(tokenId.arr, issuer.toAddress.bytes.arr)) + val makerBalanceKey = ByteStr(Bytes.concat(tokenId.arr, maker.toAddress.bytes.arr)) + + val issuerKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte))) + val makerKey = ByteStr(Bytes.concat(contractId.arr, Array(1.toByte))) + + //Statemap keys + newState.contractInfo(issuerKey) shouldEqual Some(DataEntry(issuer.toAddress.bytes.arr, DataType.Address)) + newState.contractInfo(makerKey) shouldEqual Some(DataEntry(maker.toAddress.bytes.arr, DataType.Address)) + newState.tokenAccountBalance(issuerBalanceKey) shouldBe 1L + newState.tokenAccountBalance(makerBalanceKey) shouldBe 1L + } + } + } + + val preconditionsNonFungibleContractV2UpdateListValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContract <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractId = regContract.contractId + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractId, updateListData, updateListType, attach, fee, ts) + + } yield (genesis, genesis2, regContract, issue, updateList1, updateList2) + + property("Execute update list in non fungible contract V2") { + forAll(preconditionsNonFungibleContractV2UpdateListValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(reg.timestamp, Seq(reg, issue))), + TestBlock.createWithTxStatus(updateList1.timestamp, Seq(updateList1), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = reg.contractId.bytes + val updateLister = updateList1.proofs.firstCurveProof.explicitGet().publicKey + val updateListKey = ByteStr(Bytes.concat(contractId.arr, Array(0.toByte), DataEntry(updateLister.toAddress.bytes.arr, DataType.Address).bytes)) + + newState.contractInfo(updateListKey) shouldEqual Some(DataEntry(Array(0.toByte), DataType.Boolean)) + } + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(reg.timestamp, Seq(reg, issue, updateList2))), + TestBlock.createWithTxStatus(updateList1.timestamp, Seq(updateList1), TransactionStatus.Success)) { (blockDiff, _) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + } + } + } + + val preconditionsNonFungibleWhiteContractV2SendValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractWhite <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractWhiteId = regContractWhite.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractWhiteId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + send <- sendNonFungibleV2Gen(master, contractWhiteId, user, 0, attach, fee, ts) + + + } yield (genesis, genesis2, regContractWhite, issue, updateList1, updateList2, updateList3, updateList4, send) + + property("Execute send in non fungible white contract") { + forAll(preconditionsNonFungibleWhiteContractV2SendValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, + updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, send: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractWhite, issue, updateList3, updateList4, updateList1, updateList2))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regContractWhite.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val master = regContractWhite.proofs.firstCurveProof.explicitGet().publicKey + val user = genesis2.recipient + + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val userBalanceKey = ByteStr(Bytes.concat(tokenId.arr, user.bytes.arr)) + + newState.tokenAccountBalance(masterBalanceKey) shouldBe 0L + newState.tokenAccountBalance(userBalanceKey) shouldBe 1L + } + } + } + + val preconditionsNonFungibleBlackContractV2SendValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractBlack <- nonFungibleBlackContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractBlack <- registerNonFungibleV2Gen(master, contractBlack, dataStack, description, fee + 10000000000L, ts) + contractBlackId = regContractBlack.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractBlackId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + send <- sendNonFungibleV2Gen(master, contractBlackId, user, 0, attach, fee, ts) + } yield (genesis, genesis2, regContractBlack, issue, updateList1, updateList2, updateList3, updateList4, send) + + property("Execute send in non fungible black contract") { + forAll(preconditionsNonFungibleBlackContractV2SendValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, + updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, send: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractBlack, issue, updateList3, updateList4, updateList1, updateList2))), + TestBlock.createWithTxStatus(send.timestamp, Seq(send), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regContractBlack.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val master = regContractBlack.proofs.firstCurveProof.explicitGet().publicKey + val user = genesis2.recipient + + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val userBalanceKey = ByteStr(Bytes.concat(tokenId.arr, user.bytes.arr)) + + newState.tokenAccountBalance(masterBalanceKey) shouldBe 0L + newState.tokenAccountBalance(userBalanceKey) shouldBe 1L + } + } + } + + val preconditionsNonFungibleWhiteContractV2TransferValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractWhite <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractWhiteId = regContractWhite.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractWhiteId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + + transferData = Seq(master.toAddress.bytes.arr, user.toAddress.bytes.arr, Ints.toByteArray(0)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Int32) + transfer <- transferNonFungibleV2Gen(master, contractWhiteId, transferData, transferType, attach, fee, ts) + + + } yield (genesis, genesis2, regContractWhite, issue, updateList1, updateList2, updateList3, updateList4, transfer) + + property("Execute transfer in non fungible white contract") { + forAll(preconditionsNonFungibleWhiteContractV2TransferValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, + updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, transfer: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractWhite, issue, updateList3, updateList4, updateList1, updateList2))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regContractWhite.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val master = regContractWhite.proofs.firstCurveProof.explicitGet().publicKey + val user = genesis2.recipient + + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val userBalanceKey = ByteStr(Bytes.concat(tokenId.arr, user.bytes.arr)) + + newState.tokenAccountBalance(masterBalanceKey) shouldBe 0L + newState.tokenAccountBalance(userBalanceKey) shouldBe 1L + } + } + } + + val preconditionsNonFungibleBlackContractV2TransferValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractBlack <- nonFungibleBlackContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractBlack <- registerNonFungibleV2Gen(master, contractBlack, dataStack, description, fee + 10000000000L, ts) + contractBlackId = regContractBlack.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractBlackId, issueData, attach, fee, ts+1) + + updateListData = Seq(user.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(user.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + transferData = Seq(master.toAddress.bytes.arr, user.toAddress.bytes.arr, Ints.toByteArray(0)) + transferType = Seq(DataType.Address, DataType.Address, DataType.Int32) + transfer <- transferNonFungibleV2Gen(master, contractBlackId, transferData, transferType, attach, fee, ts) + + + } yield (genesis, genesis2, regContractBlack, issue, updateList1, updateList2, updateList3, updateList4, transfer) + + property("Execute transfer in non fungible black contract") { + forAll(preconditionsNonFungibleWhiteContractV2TransferValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, + updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, transfer: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(updateList2.timestamp, Seq(regContractBlack, issue, updateList1, updateList2))), + TestBlock.createWithTxStatus(transfer.timestamp, Seq(transfer), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regContractBlack.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val master = regContractBlack.proofs.firstCurveProof.explicitGet().publicKey + val user = genesis2.recipient + + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val userBalanceKey = ByteStr(Bytes.concat(tokenId.arr, user.bytes.arr)) + + newState.tokenAccountBalance(masterBalanceKey) shouldBe 0L + newState.tokenAccountBalance(userBalanceKey) shouldBe 1L + } + } + } + + val preconditionsNonFungibleBlackContractV2DepositValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractBlack <- nonFungibleBlackContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractBlack <- registerNonFungibleV2Gen(master, contractBlack, dataStack, description, fee + 10000000000L, ts) + contractBlackId = regContractBlack.contractId + tokenId = tokenIdFromBytes(contractBlackId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + contractLock <- lockContractGen + dataStack: Seq[DataEntry] <- initLockContractDataStackGen(tokenId.arr) + description <- validDescStringGen + regContractLock <- registerLockGen(master, contractLock, dataStack, description, fee + 10000000000L, ts) + contractLockId = regContractLock.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractBlackId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + deposit <- depositNonFungibleV2Gen(master, contractBlackId, depositData, depositType, attach, fee, ts) + + } yield (genesis, genesis2, regContractBlack, regContractLock, issue, updateList1, deposit) + + property("Execute deposit in non fungible black contract") { + forAll(preconditionsNonFungibleBlackContractV2DepositValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, regContractLock: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue))), + TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regContractBlack.contractId.bytes + val lockContractId = regContractLock.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val master = regContractBlack.proofs.firstCurveProof.explicitGet().publicKey + + + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val contractBalanceKey = ByteStr(Bytes.concat(tokenId.arr, lockContractId.arr)) + + newState.tokenAccountBalance(masterBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractBalanceKey) shouldBe 1L + } + } + } + + val preconditionsNonFungibleWhiteContractV2DepositValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractWhite <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractWhiteId = regContractWhite.contractId + tokenId = tokenIdFromBytes(contractWhiteId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + contractLock <- lockContractGen + dataStack: Seq[DataEntry] <- initLockContractDataStackGen(tokenId.arr) + description <- validDescStringGen + regContractLock <- registerLockGen(master, contractLock, dataStack, description, fee + 10000000000L, ts) + contractLockId = regContractLock.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractWhiteId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + deposit <- depositNonFungibleV2Gen(master, contractWhiteId, depositData, depositType, attach, fee, ts) + + } yield (genesis, genesis2, regContractWhite, regContractLock, issue, updateList1, updateList2, updateList3, updateList4, deposit) + + property("Execute deposit in non fungible white contract") { + forAll(preconditionsNonFungibleWhiteContractV2DepositValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, regContractLock: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2))), + TestBlock.createWithTxStatus(deposit.timestamp, Seq(deposit), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regContractWhite.contractId.bytes + val lockContractId = regContractLock.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val master = regContractWhite.proofs.firstCurveProof.explicitGet().publicKey + + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val contractBalanceKey = ByteStr(Bytes.concat(tokenId.arr, lockContractId.arr)) + + newState.tokenAccountBalance(masterBalanceKey) shouldBe 0L + newState.tokenAccountBalance(contractBalanceKey) shouldBe 1L + } + } + } + + val preconditionsNonFungibleBlackContractV2WithdrawValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractBlack <- nonFungibleBlackContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractBlack <- registerNonFungibleV2Gen(master, contractBlack, dataStack, description, fee + 10000000000L, ts) + contractBlackId = regContractBlack.contractId + tokenId = tokenIdFromBytes(contractBlackId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + contractLock <- lockContractGen + dataStack: Seq[DataEntry] <- initLockContractDataStackGen(tokenId.arr) + description <- validDescStringGen + regContractLock <- registerLockGen(master, contractLock, dataStack, description, fee + 10000000000L, ts) + contractLockId = regContractLock.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractBlackId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractBlackId, updateListData, updateListType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + deposit <- depositNonFungibleV2Gen(master, contractBlackId, depositData, depositType, attach, fee, ts) + + withdrawData = Seq(contractLockId.bytes.arr, master.toAddress.bytes.arr, Ints.toByteArray(0)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Int32) + withdraw <- withdrawNonFungibleV2Gen(master, contractBlackId, withdrawData, withdrawType, attach, fee, ts) + + } yield (genesis, genesis2, regContractBlack, regContractLock, issue, updateList1, updateList2, deposit, withdraw) + + property("Execute withdraw in non fungible black contract") { + forAll(preconditionsNonFungibleBlackContractV2WithdrawValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractBlack: RegisterContractTransaction, regContractLock: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractBlack, regContractLock, issue, deposit))), + TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regContractBlack.contractId.bytes + val lockContractId = regContractLock.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val master = regContractBlack.proofs.firstCurveProof.explicitGet().publicKey + + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val contractBalanceKey = ByteStr(Bytes.concat(tokenId.arr, lockContractId.arr)) + + newState.tokenAccountBalance(masterBalanceKey) shouldBe 1L + newState.tokenAccountBalance(contractBalanceKey) shouldBe 0L + } + } + } + + val preconditionsNonFungibleWhiteContractV2WithdrawValidTest: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (master, ts, fee) <- ContractGenHelper.basicContractTestGen() + contractWhite <- nonFungibleWhiteContract + user <- accountGen + dataStack: Seq[DataEntry] <- initTokenDataStackGen() + description <- validDescStringGen + regContractWhite <- registerNonFungibleV2Gen(master, contractWhite, dataStack, description, fee + 10000000000L, ts) + contractWhiteId = regContractWhite.contractId + tokenId = tokenIdFromBytes(contractWhiteId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + contractLock <- lockContractGen + dataStack: Seq[DataEntry] <- initLockContractDataStackGen(tokenId.arr) + description <- validDescStringGen + regContractLock <- registerLockGen(master, contractLock, dataStack, description, fee + 10000000000L, ts) + contractLockId = regContractLock.contractId + + genesis <- genesisNonFungibleV2Gen(master, ts) + genesis2 <- genesisNonFungibleV2Gen(user, ts) + + issueData = "first token" + attach <- genBoundedString(2, ExecuteContractFunctionTransaction.MaxDescriptionSize) + issue <- issueNonFungibleV2Gen(master, contractWhiteId, issueData, attach, fee, ts+1) + + updateListData = Seq(master.toAddress.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList1 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(1.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList2 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(master.toAddress.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.Address, DataType.Boolean) + updateList3 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + updateListData = Seq(contractLockId.bytes.arr, Array(0.toByte)) + updateListType = Seq(DataType.ContractAccount, DataType.Boolean) + updateList4 <- updateListNonFungibleV2Gen(master, contractWhiteId, updateListData, updateListType, attach, fee, ts) + + depositData = Seq(master.toAddress.bytes.arr, contractLockId.bytes.arr, Ints.toByteArray(0)) + depositType = Seq(DataType.Address, DataType.ContractAccount, DataType.Int32) + deposit <- depositNonFungibleV2Gen(master, contractWhiteId, depositData, depositType, attach, fee, ts) + + withdrawData = Seq(contractLockId.bytes.arr, master.toAddress.bytes.arr, Ints.toByteArray(0)) + withdrawType = Seq(DataType.ContractAccount, DataType.Address, DataType.Int32) + withdraw <- withdrawNonFungibleV2Gen(master, contractWhiteId, withdrawData, withdrawType, attach, fee, ts) + + } yield (genesis, genesis2, regContractWhite, regContractLock, issue, updateList1, updateList2, updateList3, updateList4, deposit, withdraw) + + property("Execute withdraw in non fungible white contract") { + forAll(preconditionsNonFungibleWhiteContractV2WithdrawValidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regContractWhite: RegisterContractTransaction, regContractLock: RegisterContractTransaction, + issue: ExecuteContractFunctionTransaction, updateList1: ExecuteContractFunctionTransaction, updateList2: ExecuteContractFunctionTransaction, updateList3: ExecuteContractFunctionTransaction, updateList4: ExecuteContractFunctionTransaction, deposit: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(issue.timestamp, Seq(regContractWhite, regContractLock, issue, updateList1, updateList2, deposit))), + TestBlock.createWithTxStatus(withdraw.timestamp, Seq(withdraw), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val contractId = regContractWhite.contractId.bytes + val lockContractId = regContractLock.contractId.bytes + val tokenId = tokenIdFromBytes(contractId.arr, Ints.toByteArray(0)).explicitGet() + val master = regContractWhite.proofs.firstCurveProof.explicitGet().publicKey + + val masterBalanceKey = ByteStr(Bytes.concat(tokenId.arr, master.toAddress.bytes.arr)) + val contractBalanceKey = ByteStr(Bytes.concat(tokenId.arr, lockContractId.arr)) + + newState.tokenAccountBalance(masterBalanceKey) shouldBe 1L + newState.tokenAccountBalance(contractBalanceKey) shouldBe 0L + } + } + } +} \ No newline at end of file From aeb2a42abbc4f47bcf2dca106cb70819e43cadfd Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 29 Jun 2021 16:14:44 +0800 Subject: [PATCH 349/391] Remove unused imports --- .../token/ExecuteNonFungibleContractV2ValidDiffTest.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2ValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2ValidDiffTest.scala index 526013b08..b551a1a68 100644 --- a/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2ValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/token/ExecuteNonFungibleContractV2ValidDiffTest.scala @@ -1,15 +1,13 @@ package vsys.blockchain.state.contract.token -import cats.Monoid import vsys.blockchain.state._ -import com.google.common.primitives.{Bytes, Ints, Shorts} +import com.google.common.primitives.{Bytes, Ints} import org.scalacheck.{Gen, Shrink} import org.scalatest.{Matchers, PropSpec} import org.scalatest.prop.{GeneratorDrivenPropertyChecks, PropertyChecks} import vsys.account.ContractAccount.tokenIdFromBytes import vsys.blockchain.block.TestBlock import vsys.blockchain.contract.{Contract, ContractGenHelper, DataEntry, DataType} -import vsys.blockchain.contract.ContractGenHelper.{feeScale, genBoundedString} import vsys.blockchain.contract.lock.LockContractGen import vsys.blockchain.contract.token.NonFungibleContractV2Gen import vsys.blockchain.state.ByteStr From 4dbf5da58dcc8070b74371fc5be40ed7e1c6e60c Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 16:29:15 +0800 Subject: [PATCH 350/391] Add helper functions for V Escrow tests --- .../vescrow/VEscrowFunctionHelperGen.scala | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/test/scala/vsys/blockchain/contract/vescrow/VEscrowFunctionHelperGen.scala diff --git a/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowFunctionHelperGen.scala b/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowFunctionHelperGen.scala new file mode 100644 index 000000000..fad1531ef --- /dev/null +++ b/src/test/scala/vsys/blockchain/contract/vescrow/VEscrowFunctionHelperGen.scala @@ -0,0 +1,42 @@ +package vsys.blockchain.contract.vescrow + +import com.google.common.primitives.Bytes +import vsys.blockchain.contract.{DataEntry, DataType} +import vsys.blockchain.state.ByteStr + +trait VEscrowFunctionHelperGen extends VEscrowContractGen { + + def getEscrowContractStateVarKeys(vEscrowContractId: Array[Byte]): Seq[ByteStr] = { + val makerKey = ByteStr(Bytes.concat(vEscrowContractId, Array(0.toByte))) + val judgeKey = ByteStr(Bytes.concat(vEscrowContractId, Array(1.toByte))) + val tokenIdKey = ByteStr(Bytes.concat(vEscrowContractId, Array(2.toByte))) + val durationKey = ByteStr(Bytes.concat(vEscrowContractId, Array(3.toByte))) + val judgeDurationKey = ByteStr(Bytes.concat(vEscrowContractId, Array(4.toByte))) + + Seq(makerKey, judgeKey, tokenIdKey, durationKey, judgeDurationKey) + } + + def getEscrowContractStateMapKeys(vEscrowContractId: Array[Byte], orderId: Array[Byte]): Seq[ByteStr] = { + val orderPayerKey = ByteStr(Bytes.concat(vEscrowContractId, Array(1.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderRecipientKey = ByteStr(Bytes.concat(vEscrowContractId, Array(2.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderAmountKey = ByteStr(Bytes.concat(vEscrowContractId, Array(3.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderRecipientDepositKey = ByteStr(Bytes.concat(vEscrowContractId, Array(4.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderJudgeDepositKey = ByteStr(Bytes.concat(vEscrowContractId, Array(5.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderFeeKey = ByteStr(Bytes.concat(vEscrowContractId, Array(6.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderRecipientAmountKey = ByteStr(Bytes.concat(vEscrowContractId, Array(7.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderRefundKey = ByteStr(Bytes.concat(vEscrowContractId, Array(8.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderRecipientRefundKey = ByteStr(Bytes.concat(vEscrowContractId, Array(9.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderExpirationTimeKey = ByteStr(Bytes.concat(vEscrowContractId, Array(10.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderStatusKey = ByteStr(Bytes.concat(vEscrowContractId, Array(11.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderRepDepositStatusKey = ByteStr(Bytes.concat(vEscrowContractId, Array(12.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderJudgeDepositStatusKey = ByteStr(Bytes.concat(vEscrowContractId, Array(13.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderSubmitStatusKey = ByteStr(Bytes.concat(vEscrowContractId, Array(14.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderJudgeStatusKey = ByteStr(Bytes.concat(vEscrowContractId, Array(15.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderRepLockedAmountKey = ByteStr(Bytes.concat(vEscrowContractId, Array(16.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + val orderJudgeLockedAmountKey = ByteStr(Bytes.concat(vEscrowContractId, Array(17.toByte), DataEntry.create(orderId, DataType.ShortBytes).right.get.bytes)) + + Seq(orderPayerKey, orderRecipientKey, orderAmountKey, orderRecipientDepositKey, orderJudgeDepositKey, orderFeeKey, + orderRecipientAmountKey, orderRefundKey, orderRecipientRefundKey, orderExpirationTimeKey, orderStatusKey, orderRepDepositStatusKey, + orderJudgeDepositStatusKey, orderSubmitStatusKey, orderJudgeStatusKey, orderRepLockedAmountKey, orderJudgeLockedAmountKey) + } +} \ No newline at end of file From df9ad12342a1dd608263d2a005f716a1821adac4 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 29 Jun 2021 16:29:50 +0800 Subject: [PATCH 351/391] Add checks for db state var and state map values --- .../ExecuteVEscrowContractValidDiffTest.scala | 429 +++++++++++++++++- 1 file changed, 418 insertions(+), 11 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractValidDiffTest.scala index a937f41ce..5285ff0f4 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vescrow/ExecuteVEscrowContractValidDiffTest.scala @@ -6,12 +6,12 @@ import org.scalatest.{Matchers, PropSpec} import vsys.blockchain.block.TestBlock import vsys.blockchain.contract._ import vsys.blockchain.contract.token.SystemContractGen -import vsys.blockchain.contract.vescrow.VEscrowContractGen +import vsys.blockchain.contract.vescrow.{VEscrowContractGen, VEscrowFunctionHelperGen} import vsys.blockchain.state.diffs._ import vsys.blockchain.transaction.contract._ import vsys.blockchain.state._ import vsys.blockchain.transaction.{GenesisTransaction, TransactionGen, TransactionStatus} -import com.google.common.primitives.{Ints, Longs} +import com.google.common.primitives.{Bytes, Ints, Longs} import vsys.account.ContractAccount import vsys.account.ContractAccount.tokenIdFromBytes @@ -21,7 +21,8 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec with Matchers with TransactionGen with SystemContractGen - with VEscrowContractGen { + with VEscrowContractGen + with VEscrowFunctionHelperGen { private implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) @@ -43,14 +44,14 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() initVEscrowDataStack <- initVEscrowDataStackGen(tokenId.arr, 1000000000L, 1000000000L) regVEscrow <- registerVEscrowGen(judge, vEscrow, initVEscrowDataStack, "test", fee, ts) - judgeDepositVSYSData = Seq(judge.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) - recipientDepositVSYSData = Seq(recipient.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) - payerDepositVSYSData = Seq(payer.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000000000000L)) + judgeDepositVSYSData = Seq(judge.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000L)) + recipientDepositVSYSData = Seq(recipient.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000L)) + payerDepositVSYSData = Seq(payer.toAddress.bytes.arr, regVEscrow.contractId.bytes.arr, Longs.toByteArray(1000L)) depositVSYSDataType = Seq(DataType.Address, DataType.ContractAccount, DataType.Amount) judgeDepositVSYS <- depositVSYSGen(judge, judgeDepositVSYSData, depositVSYSDataType, attach, fee, ts + 1) recipientDepositVSYS <- depositVSYSGen(recipient, recipientDepositVSYSData, depositVSYSDataType, attach, fee, ts + 2) payerDepositVSYS <- depositVSYSGen(payer, payerDepositVSYSData, depositVSYSDataType, attach, fee, ts + 3) - withdrawVSYSData = Seq(regVEscrow.contractId.bytes.arr, judge.toAddress.bytes.arr, Longs.toByteArray(100000L)) + withdrawVSYSData = Seq(regVEscrow.contractId.bytes.arr, judge.toAddress.bytes.arr, Longs.toByteArray(1000L)) withdrawVSYSDataType = Seq(DataType.ContractAccount, DataType.Address, DataType.Amount) judgeWithdrawVSYS <- withdrawVSYSGen(judge, withdrawVSYSData, withdrawVSYSDataType, attach, fee, ts + 4) createVEscrow <- createVEscrowGen(payer, regVEscrow.contractId, recipient.toAddress, 1000L, 1000L, 1000L, 10L, 10L, ts + 100L, attach, fee, ts + 5) @@ -78,17 +79,59 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS))), TestBlock.createWithTxStatus(judgeWithdrawVSYS.timestamp, Seq(judgeWithdrawVSYS), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val tokenId = tokenIdFromBytes(ContractAccount.systemContractId.bytes.arr, Ints.toByteArray(0)).explicitGet() + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateVarKeys = getEscrowContractStateVarKeys(regVEscrow.contractId.bytes.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 0L + + newState.contractInfo(contractStateVarKeys.head) shouldEqual Some(DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get) + newState.contractInfo(contractStateVarKeys(1)) shouldEqual Some(DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get) + newState.contractInfo(contractStateVarKeys(2)) shouldEqual Some(DataEntry.create(tokenId.arr, DataType.TokenId).right.get) + newState.contractInfo(contractStateVarKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000000000L), DataType.Timestamp).right.get) + newState.contractInfo(contractStateVarKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000000000L), DataType.Timestamp).right.get) } } } property("v-escrow able to register and create") { - forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, _, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, + forAll(preconditionsAndExecuteContractEscrow) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, genesis3: GenesisTransaction, regVEscrow: RegisterContractTransaction, judgeDepositVSYS: ExecuteContractFunctionTransaction, _, payerDepositVSYS: ExecuteContractFunctionTransaction, _, createVEscrow: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _, _, _, _, _, _, _) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis3)), TestBlock.create(judgeDepositVSYS.timestamp, Seq(regVEscrow, judgeDepositVSYS, payerDepositVSYS))), TestBlock.createWithTxStatus(createVEscrow.timestamp, Seq(createVEscrow), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 1000L + newState.contractNumInfo(payerBalanceKey) shouldEqual 0L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(9)) shouldEqual Some(DataEntry.create(Longs.toByteArray(genesis.timestamp + 100), DataType.Timestamp).right.get) // orderExpirationTime + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(0L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(0L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -102,6 +145,37 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow))), TestBlock.createWithTxStatus(recipientDepositToOrder.timestamp, Seq(recipientDepositToOrder, judgeDepositToOrder), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 0L + newState.contractNumInfo(payerBalanceKey) shouldEqual 0L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 0L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(9)) shouldEqual Some(DataEntry.create(Longs.toByteArray(genesis.timestamp + 100), DataType.Timestamp).right.get) // orderExpirationTime + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -115,6 +189,37 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow, judgeDepositToOrder))), TestBlock.createWithTxStatus(payerCancelOrder.timestamp, Seq(payerCancelOrder), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 1000L + newState.contractNumInfo(payerBalanceKey) shouldEqual 1000L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 1000L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(9)) shouldEqual Some(DataEntry.create(Longs.toByteArray(genesis.timestamp + 100), DataType.Timestamp).right.get) // orderExpirationTime + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(0L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -128,6 +233,37 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow, judgeDepositToOrder))), TestBlock.createWithTxStatus(recipientCancelOrder.timestamp, Seq(recipientCancelOrder), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 1000L + newState.contractNumInfo(payerBalanceKey) shouldEqual 1000L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 1000L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(9)) shouldEqual Some(DataEntry.create(Longs.toByteArray(genesis.timestamp + 100), DataType.Timestamp).right.get) // orderExpirationTime + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(0L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -141,6 +277,37 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder))), TestBlock.createWithTxStatus(judgeCancelOrder.timestamp, Seq(judgeCancelOrder), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 1000L + newState.contractNumInfo(payerBalanceKey) shouldEqual 1000L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 1000L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(9)) shouldEqual Some(DataEntry.create(Longs.toByteArray(genesis.timestamp + 100), DataType.Timestamp).right.get) // orderExpirationTime + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(0L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -150,10 +317,40 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, _, _, _, submitWork: ExecuteContractFunctionTransaction, _, _, _, _, _, _, _) => - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(judgeDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder))), TestBlock.createWithTxStatus(submitWork.timestamp, Seq(submitWork), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 0L + newState.contractNumInfo(payerBalanceKey) shouldEqual 0L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 0L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -163,10 +360,40 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, _, _, _, submitWork: ExecuteContractFunctionTransaction, approveWork: ExecuteContractFunctionTransaction, _, _, _, _, _, _) => - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(submitWork.timestamp, Seq(regVEscrow, judgeDepositVSYS, recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork))), TestBlock.createWithTxStatus(approveWork.timestamp, Seq(approveWork), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 1010L + newState.contractNumInfo(payerBalanceKey) shouldEqual 0L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 1990L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -176,10 +403,40 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec judgeDepositVSYS: ExecuteContractFunctionTransaction, recipientDepositVSYS: ExecuteContractFunctionTransaction, payerDepositVSYS: ExecuteContractFunctionTransaction, _, createVEscrow: ExecuteContractFunctionTransaction, recipientDepositToOrder: ExecuteContractFunctionTransaction, judgeDepositToOrder: ExecuteContractFunctionTransaction, _, _, _, submitWork: ExecuteContractFunctionTransaction, _, applyToJudge: ExecuteContractFunctionTransaction, _, _, _, _, _) => - assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(recipientDepositToOrder.timestamp, Seq(regVEscrow, judgeDepositVSYS, + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2, genesis3)), TestBlock.create(submitWork.timestamp, Seq(regVEscrow, judgeDepositVSYS, recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork))), TestBlock.createWithTxStatus(applyToJudge.timestamp, Seq(applyToJudge), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 0L + newState.contractNumInfo(payerBalanceKey) shouldEqual 0L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 0L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -193,6 +450,36 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork, applyToJudge))), TestBlock.createWithTxStatus(judgeWork.timestamp, Seq(judgeWork), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 1010L + newState.contractNumInfo(payerBalanceKey) shouldEqual 0 + newState.contractNumInfo(recipientBalanceKey) shouldEqual 1990L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -206,6 +493,36 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder))), TestBlock.createWithTxStatus(submitPenalty.timestamp + 1000000000L, Seq(submitPenalty), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 1010L + newState.contractNumInfo(payerBalanceKey) shouldEqual 1990L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 0L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -219,6 +536,36 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork, applyToJudge))), TestBlock.createWithTxStatus(payerRefund.timestamp + 1000000000L, Seq(payerRefund), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 0L + newState.contractNumInfo(payerBalanceKey) shouldEqual 10L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 2990L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -233,6 +580,36 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork, applyToJudge))), TestBlock.createWithTxStatus(recipientRefund.timestamp + 1000000000L, Seq(recipientRefund), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 0L + newState.contractNumInfo(payerBalanceKey) shouldEqual 10L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 2990L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } @@ -246,6 +623,36 @@ class ExecuteVEscrowContractValidDiffTest extends PropSpec recipientDepositVSYS, payerDepositVSYS, createVEscrow, recipientDepositToOrder, judgeDepositToOrder, submitWork))), TestBlock.createWithTxStatus(recipientCollect.timestamp + 1000000000L, Seq(recipientCollect), TransactionStatus.Success)) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + val judge = regVEscrow.proofs.firstCurveProof.explicitGet().publicKey + val payer = payerDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + val recipient = recipientDepositVSYS.proofs.firstCurveProof.explicitGet().publicKey + + val judgeBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(judge.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val payerBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(payer.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val recipientBalanceKey = ByteStr(Bytes.concat(regVEscrow.contractId.bytes.arr, Array(0.toByte), DataEntry.create(recipient.toAddress.bytes.arr, DataType.Address).right.get.bytes)) + val contractStateMapKeys = getEscrowContractStateMapKeys(regVEscrow.contractId.bytes.arr, createVEscrow.id.arr) + + newState.contractNumInfo(judgeBalanceKey) shouldEqual 1010L + newState.contractNumInfo(payerBalanceKey) shouldEqual 0L + newState.contractNumInfo(recipientBalanceKey) shouldEqual 1990L + + newState.contractInfo(contractStateMapKeys.head) shouldEqual Some(DataEntry.create(genesis3.recipient.bytes.arr, DataType.Address).right.get) // orderPayer + newState.contractInfo(contractStateMapKeys(1)) shouldEqual Some(DataEntry.create(genesis2.recipient.bytes.arr, DataType.Address).right.get) // orderRecipient + newState.contractInfo(contractStateMapKeys(2)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderAmount + newState.contractInfo(contractStateMapKeys(3)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRecipientDeposit + newState.contractInfo(contractStateMapKeys(4)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeDeposit + newState.contractInfo(contractStateMapKeys(5)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderFee + newState.contractInfo(contractStateMapKeys(6)) shouldEqual Some(DataEntry.create(Longs.toByteArray(990L), DataType.Amount).right.get) // orderRecipientAmount + newState.contractInfo(contractStateMapKeys(7)) shouldEqual Some(DataEntry.create(Longs.toByteArray(10L), DataType.Amount).right.get) // orderRefund + newState.contractInfo(contractStateMapKeys(8)) shouldEqual Some(DataEntry.create(Longs.toByteArray(2990L), DataType.Amount).right.get) // orderRecipientRefund + newState.contractInfo(contractStateMapKeys(10)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderStatus + newState.contractInfo(contractStateMapKeys(11)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderRepDepositStatus + newState.contractInfo(contractStateMapKeys(12)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderJudgeDepositStatus + newState.contractInfo(contractStateMapKeys(13)) shouldEqual Some(DataEntry.create(Array(1.toByte), DataType.Boolean).right.get) // orderSubmitStatus + newState.contractInfo(contractStateMapKeys(14)) shouldEqual Some(DataEntry.create(Array(0.toByte), DataType.Boolean).right.get) // orderJudgeStatus + newState.contractInfo(contractStateMapKeys(15)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderRepLockedAmount + newState.contractInfo(contractStateMapKeys(16)) shouldEqual Some(DataEntry.create(Longs.toByteArray(1000L), DataType.Amount).right.get) // orderJudgeLockedAmount } } } From c7f680b3f8d8419e14737b8fe1737c55e10305ac Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 30 Jun 2021 13:16:54 +0800 Subject: [PATCH 352/391] update validation logic --- .../scala/vsys/blockchain/state/diffs/CommonValidation.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala b/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala index ff39f6838..789aeda3f 100644 --- a/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala +++ b/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala @@ -46,7 +46,9 @@ object CommonValidation { (c != ContractPermitted.contract && c != ContractPermitted.contractWithoutSplit)) Left(GenericError(s"deposit withdraw contracts must not appear before height=${settings.allowDepositWithdrawContractAfterHeight}")) - else Right(tx) + else if (c == ContractLock.contract || c == ContractPaymentChannel.contract || c == ContractNonFungible.contract || c == ContractPermitted.contract || c == ContractPermitted.contractWithoutSplit) + Right(tx) + else Left(GenericError(s"unsupported contracts")) } def disallowBeforeActivationHeight[T <: Transaction](settings: FunctionalitySettings, h: Int, tx: T): Either[ValidationError, T] = From 872abb3c01b8cc0d16d93fba734b04145889cacc Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 5 Jul 2021 11:29:55 +0800 Subject: [PATCH 353/391] update contract validation --- .../vsys/blockchain/state/diffs/CommonValidation.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala b/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala index 33c8e9e31..e1930f845 100644 --- a/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala +++ b/src/main/scala/vsys/blockchain/state/diffs/CommonValidation.scala @@ -45,6 +45,10 @@ object CommonValidation { private def isDepositWithdrawContracts(c: Contract): Boolean = c == ContractLock.contract || c == ContractPaymentChannel.contract || c == ContractNonFungible.contract + private def isExchangeContracts(c: Contract): Boolean = + c == ContractAtomicSwap.contract || c == ContractVEscrow.contract || c == ContractVOption.contract || c == ContractVStableSwap.contract || c == ContractVSwap.contract || + c == ContractTokenV2.contractTokenBlackList || c == ContractTokenV2.contractTokenWhiteList || c == ContractNonFungibleV2.contractNFTBlacklist || c == ContractNonFungibleV2.contractNFTWhitelist + private def disallowInvalidContractTxs[T <: Transaction](settings: FunctionalitySettings, h: Int, tx: T, c: Contract): Either[ValidationError, T] = { if (h <= settings.allowContractTransactionAfterHeight) Left(GenericError(s"must not appear before height=${settings.allowContractTransactionAfterHeight}")) @@ -52,7 +56,9 @@ object CommonValidation { Left(GenericError(s"deposit withdraw contracts must not appear before height=${settings.allowDepositWithdrawContractAfterHeight}")) else if (h <= settings.allowExchangeContractAfterHeight && !isTokenContracts(c) && !isDepositWithdrawContracts(c)) Left(GenericError(s"exchange contracts must not appear before height=${settings.allowExchangeContractAfterHeight}")) - else Right(tx) + else if (isTokenContracts(c) || isDepositWithdrawContracts(c) || isExchangeContracts(c)) + Right(tx) + else Left(GenericError(s"unsupported contracts")) } def disallowBeforeActivationHeight[T <: Transaction](settings: FunctionalitySettings, h: Int, tx: T): Either[ValidationError, T] = From 07c8af2bc646d1aaa2ad91c0cf4debf54b79f9a9 Mon Sep 17 00:00:00 2001 From: ncying <38449461+ncying@users.noreply.github.com> Date: Fri, 9 Jul 2021 11:24:48 +0800 Subject: [PATCH 354/391] update workflows --- .github/workflows/build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b6eb75b0f..98c300f49 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,10 +10,11 @@ jobs: steps: - name: install scala run: | - echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823 + echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list + echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list + curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add sudo apt-get update - sudo apt-get install -y sbt + sudo apt-get install sbt - uses: actions/checkout@v2 From d00d1727c736b277d6f06966934897a2bc37824f Mon Sep 17 00:00:00 2001 From: zl730 Date: Tue, 13 Jul 2021 13:20:22 +0800 Subject: [PATCH 355/391] fix bigint serializing --- .../vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 8785b8102..f2fc5954e 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -83,7 +83,7 @@ object BasicOpcDiff extends OpcDiffer { case Int32 => formatResB[Int] (addLeadingZeros(bytes, 4), Int32) case Amount => formatResB[Long] (addLeadingZeros(bytes, 8), Amount) case Timestamp => formatResB[Long] (addLeadingZeros(bytes, 8), Timestamp) - case BigInteger => formatResB[BigInt](bytes.dropRight(1).dropWhile(i => i == 0) ++ bytes.takeRight(1), BigInteger) + case BigInteger => formatResB[BigInt](bigintBytes(bytes), BigInteger) case _ => Left(ContractUnsupportedOPC) } } @@ -128,6 +128,14 @@ object BasicOpcDiff extends OpcDiffer { val Not = BasicTypeVal(14, 3, Seq(1), (b, d) => not(d(b(1)))) } + private def bigintBytes (bytes: Array[Byte]): Array[Byte] = { + val x = bytes.dropRight(1).dropWhile(i => i == 0) ++ bytes.takeRight(1) + x.headOption match { + case Some(a: Byte) if a < 0 => Array(0.toByte) ++ x + case _ => x + } + } + private def formatRes[T] (res: T, dt: DataTypeVal[T]): Either[ValidationError, DataEntry] = formatResB[T](dt.serializer(res), dt) From fe843f680612c47b1820c1c7a0df040c5d31c35c Mon Sep 17 00:00:00 2001 From: zl730 Date: Tue, 20 Jul 2021 13:04:29 +0800 Subject: [PATCH 356/391] support negative int32 and bigint value --- .../state/opcdiffs/BasicOpcDiff.scala | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index f2fc5954e..01ff82a18 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -80,9 +80,9 @@ object BasicOpcDiff extends OpcDiffer { }) flatMap { bytes => { val to: DataTypeVal[_] = DataTypeObj.deserializer(t.data) to match { - case Int32 => formatResB[Int] (addLeadingZeros(bytes, 4), Int32) - case Amount => formatResB[Long] (addLeadingZeros(bytes, 8), Amount) - case Timestamp => formatResB[Long] (addLeadingZeros(bytes, 8), Timestamp) + case Int32 => formatResB[Int] (formatSignedByteArrayWithLength(bytes, 4), Int32) + case Amount => formatResB[Long] (formatPositiveByteArrayWithLength(bytes, 8), Amount) + case Timestamp => formatResB[Long] (formatPositiveByteArrayWithLength(bytes, 8), Timestamp) case BigInteger => formatResB[BigInt](bigintBytes(bytes), BigInteger) case _ => Left(ContractUnsupportedOPC) } @@ -91,11 +91,25 @@ object BasicOpcDiff extends OpcDiffer { case _ => Left(ContractInvalidOPCData) } - def addLeadingZeros(in: Array[Byte], length: Int): Array[Byte] = - if (in.length - length > 0) { + private def formatPositiveByteArrayWithLength(in: Array[Byte], length: Int): Array[Byte] = + if (in.length > length) { in.take(in.length - length).dropWhile(i => i == 0) ++ in.takeRight(length) + } else if (in(0) >= 0) { + new Array[Byte](length - in.length) ++ in } else { - (new Array[Byte](0.max(length - in.length)) ++ in).takeRight(length) + new Array[Byte](length + 1) // make overflow error when in < 0 + } + + private def formatSignedByteArrayWithLength(in: Array[Byte], length: Int): Array[Byte] = + if (in(0) >= 0) { + formatPositiveByteArrayWithLength(in, length) + } else if (in.length > length) { + val right = in.takeRight(length) + if (right(0) >= 0) in else { + in.take(in.length - length).dropWhile(i => i == -1) ++ right + } + } else { + Array.fill[Byte](length - in.length)(-1) ++ in } def concat(x: DataEntry, y: DataEntry): Either[ValidationError, DataEntry] = @@ -129,10 +143,18 @@ object BasicOpcDiff extends OpcDiffer { } private def bigintBytes (bytes: Array[Byte]): Array[Byte] = { - val x = bytes.dropRight(1).dropWhile(i => i == 0) ++ bytes.takeRight(1) - x.headOption match { - case Some(a: Byte) if a < 0 => Array(0.toByte) ++ x - case _ => x + if (bytes(0) >= 0) { + val x = bytes.dropRight(1).dropWhile(i => i == 0) ++ bytes.takeRight(1) + x.headOption match { + case Some(a: Byte) if a < 0 => Array[Byte](0.toByte) ++ x + case _ => x + } + } else { + val x = bytes.dropRight(1).dropWhile(i => i == -1) ++ bytes.takeRight(1) + x.headOption match { + case Some(a: Byte) if a >= 0 => Array[Byte](-1.toByte) ++ x + case _ => x + } } } From 9f9d3eb00a844ed278f0afdd9cc9c80b6d4eac88 Mon Sep 17 00:00:00 2001 From: zl730 Date: Tue, 20 Jul 2021 13:15:48 +0800 Subject: [PATCH 357/391] simplify code --- .../state/opcdiffs/BasicOpcDiff.scala | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 01ff82a18..b0869f15e 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -143,18 +143,11 @@ object BasicOpcDiff extends OpcDiffer { } private def bigintBytes (bytes: Array[Byte]): Array[Byte] = { - if (bytes(0) >= 0) { - val x = bytes.dropRight(1).dropWhile(i => i == 0) ++ bytes.takeRight(1) - x.headOption match { - case Some(a: Byte) if a < 0 => Array[Byte](0.toByte) ++ x - case _ => x - } - } else { - val x = bytes.dropRight(1).dropWhile(i => i == -1) ++ bytes.takeRight(1) - x.headOption match { - case Some(a: Byte) if a >= 0 => Array[Byte](-1.toByte) ++ x - case _ => x - } + val sig = bytes(0) >> 3 + val x = bytes.dropRight(1).dropWhile(i => i == sig) ++ bytes.takeRight(1) + x.headOption match { + case Some(a: Byte) if (a >> 3) != sig => Array[Byte](sig.toByte) ++ x + case _ => x } } From 8f18cbc8644ff1a14d79960d1d82c7bdf32aa4b1 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 20 Jul 2021 15:26:30 +0800 Subject: [PATCH 358/391] add more rigorous testing to the convert opc --- .../state/opcdiffs/ConvertOpcDiffTest.scala | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala index 95aae9747..3ab1da810 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/ConvertOpcDiffTest.scala @@ -152,4 +152,87 @@ class ConvertOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriv Left(ValidationError.OverflowError) ) } + property("test different length numbers for conversion to BigInt") { + val l: List[Long] = List(1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, + 1000000000, 10000000000L, 100000000000L, 1000000000000L, 10000000000000L, 100000000000000L, + 1000000000000000L, 10000000000000000L, 100000000000000000L, 1000000000000000000L) + for (a <- l) { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(a), DataType.Amount), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(a).toByteArray.length.toShort) ++ BigInt(a).toByteArray, DataType.BigInteger)) + ) + } + for (b <- l.slice(0, 9)) { + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(b.toInt), DataType.Int32), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(b).toByteArray.length.toShort) ++ BigInt(b).toByteArray, DataType.BigInteger)) + ) + } + for (c <- l) { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(c), DataType.Timestamp), BigIntDataTypeObj) should be( + Right(DataEntry(Shorts.toByteArray(BigInt(c).toByteArray.length.toShort) ++ BigInt(c).toByteArray, DataType.BigInteger)) + ) + } + } + + property("test different length negative numbers for conversion to BigInt") { + val l: List[Long] = List(1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, + 1000000000, 10000000000L, 100000000000L, 1000000000000L, 10000000000000L, 100000000000000L, + 1000000000000000L, 10000000000000000L, 100000000000000000L, 1000000000000000000L) + for (a <- l) { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(-a), DataType.Amount), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(-a).toByteArray.length.toShort) ++ BigInt(-a).toByteArray, DataType.BigInteger)) + ) + } + for (b <- l.slice(0, 9)) { + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(-b.toInt), DataType.Int32), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(-b).toByteArray.length.toShort) ++ BigInt(-b).toByteArray, DataType.BigInteger)) + ) + } + for (c <- l) { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(-c), DataType.Timestamp), BigIntDataTypeObj) should be( + Right(DataEntry(Shorts.toByteArray(BigInt(-c).toByteArray.length.toShort) ++ BigInt(-c).toByteArray, DataType.BigInteger)) + ) + } + } + + property("test different array length numbers for conversion to BigInt") { + val l: List[Long] = List(Math.pow(2, 0).toLong, Math.pow(2, 8).toLong, Math.pow(2, 16).toLong, Math.pow(2, 24).toLong, + (Math.pow(2, 32)/2 - 1).toLong, Math.pow(2, 32).toLong, Math.pow(2, 40).toLong, Math.pow(2, 48).toLong, + Math.pow(2, 56).toLong, (Math.pow(2, 64)/2 - 1).toLong) + for (a <- l) { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(a), DataType.Amount), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(a).toByteArray.length.toShort) ++ BigInt(a).toByteArray, DataType.BigInteger)) + ) + } + for (b <- l.slice(0, 4)) { + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(b.toInt), DataType.Int32), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(b).toByteArray.length.toShort) ++ BigInt(b).toByteArray, DataType.BigInteger)) + ) + } + for (c <- l) { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(c), DataType.Timestamp), BigIntDataTypeObj) should be( + Right(DataEntry(Shorts.toByteArray(BigInt(c).toByteArray.length.toShort) ++ BigInt(c).toByteArray, DataType.BigInteger)) + ) + } + } + + property("test different array length negative numbers for conversion to BigInt") { + val l: List[Long] = List(Math.pow(2, 0).toLong, Math.pow(2, 8).toLong, Math.pow(2, 16).toLong, Math.pow(2, 24).toLong, + (Math.pow(2, 32)/2 - 1).toLong, Math.pow(2, 32).toLong, Math.pow(2, 40).toLong, Math.pow(2, 48).toLong, + Math.pow(2, 56).toLong, (Math.pow(2, 64)/2 - 1).toLong) + for (a <- l) { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(-a), DataType.Amount), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(-a).toByteArray.length.toShort) ++ BigInt(-a).toByteArray, DataType.BigInteger)) + ) + } + for (b <- l.slice(0, 4)) { + BasicOpcDiff.convertion(DataEntry(Ints.toByteArray(-b.toInt), DataType.Int32), BigIntDataTypeObj) should be ( + Right(DataEntry(Shorts.toByteArray(BigInt(-b).toByteArray.length.toShort) ++ BigInt(-b).toByteArray, DataType.BigInteger)) + ) + } + for (c <- l) { + BasicOpcDiff.convertion(DataEntry(Longs.toByteArray(-c), DataType.Timestamp), BigIntDataTypeObj) should be( + Right(DataEntry(Shorts.toByteArray(BigInt(-c).toByteArray.length.toShort) ++ BigInt(-c).toByteArray, DataType.BigInteger)) + ) + } + } } From 486ae3110951a51588bf56530a56e958325fded3 Mon Sep 17 00:00:00 2001 From: zl730 Date: Tue, 20 Jul 2021 16:16:33 +0800 Subject: [PATCH 359/391] fix digits --- .../scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index b0869f15e..3e36fcb47 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -142,11 +142,11 @@ object BasicOpcDiff extends OpcDiffer { val Not = BasicTypeVal(14, 3, Seq(1), (b, d) => not(d(b(1)))) } - private def bigintBytes (bytes: Array[Byte]): Array[Byte] = { - val sig = bytes(0) >> 3 + def bigintBytes (bytes: Array[Byte]): Array[Byte] = { + val sig = bytes(0) >> 7 val x = bytes.dropRight(1).dropWhile(i => i == sig) ++ bytes.takeRight(1) x.headOption match { - case Some(a: Byte) if (a >> 3) != sig => Array[Byte](sig.toByte) ++ x + case Some(a: Byte) if (a >> 7) != sig => Array[Byte](sig.toByte) ++ x case _ => x } } From 016055e027a2a531a5af0c2354560fb91b2678a4 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Thu, 29 Jul 2021 12:09:54 +0800 Subject: [PATCH 360/391] fix translating bigInt data type --- src/test/scala/tools/ContractTranslator.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/scala/tools/ContractTranslator.scala b/src/test/scala/tools/ContractTranslator.scala index a25efdcd7..9f8d9080d 100644 --- a/src/test/scala/tools/ContractTranslator.scala +++ b/src/test/scala/tools/ContractTranslator.scala @@ -200,6 +200,8 @@ object ContractTranslator extends App { res = res + Ints.fromByteArray(s.tail).toString } else if (s(0) == DataType.Amount.id.toByte || s(0) == DataType.Timestamp.id.toByte) { res = res + Longs.fromByteArray(s.tail).toString + } else if (s(0) == DataType.BigInteger.id.toByte) { + res = res + BigInt(s.drop(3)).toString() } else if (s(0) == DataType.Boolean.id.toByte) { if (s(1) == 1.toByte) { res = res + "true" From ea2bfc80447f1c976534cacfdc5a4ed57b44aa2e Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 3 Aug 2021 17:26:20 +0800 Subject: [PATCH 361/391] fix v swap add liquidity --- src/main/scala/vsys/blockchain/contract/ContractVSwap.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 1d3a98e79..9dcea88e7 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -246,11 +246,11 @@ object ContractVSwap { basicMultiply ++ Array(18.toByte, 15.toByte, 21.toByte), basicDivide ++ Array(21.toByte, 16.toByte, 22.toByte), basicConstantGet ++ DataEntry(Array(DataType.Amount.id.toByte), DataType.DataTypeObj).bytes ++ Array(23.toByte), - basicMin ++ Array(20.toByte, 17.toByte, 24.toByte), + basicMin ++ Array(22.toByte, 17.toByte, 24.toByte), basicConvert ++ Array(24.toByte, 23.toByte, 25.toByte), compareGreaterEqual ++ Array(25.toByte, 2.toByte, 26.toByte), assertTrue ++ Array(26.toByte), - basicMin ++ Array(22.toByte, 18.toByte, 27.toByte), + basicMin ++ Array(20.toByte, 18.toByte, 27.toByte), basicConvert ++ Array(27.toByte, 23.toByte, 28.toByte), compareGreaterEqual ++ Array(28.toByte, 3.toByte, 29.toByte), assertTrue ++ Array(29.toByte), From 9a65c78f007f1ee158dee40abcd7b145c0c46c54 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Wed, 4 Aug 2021 11:12:19 +0800 Subject: [PATCH 362/391] fix invalid add liquidity to expected result --- .../state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala index 7e44411be..e2abafac7 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapInvalidDiffTest.scala @@ -102,9 +102,9 @@ class ExecuteVSwapInvalidDiffTest extends PropSpec 10000, 1000,10, 3000, 3000) setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 1000L, 1000L, attach, fee + 10000000000L, ts) - addLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 2000L, 2000L, 900L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + addLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 3000L, 2000L, 900L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts) - addInvalidLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 3000L, 2000L, 900L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts) + addInvalidLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 2001, 2001L, 900L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts) addInvalidLiquidity2 <- addLiquidityVSwapGen(master, regVSwap.contractId, 2000L, 2000L, 9000L, 900L, ts + 1000000000000L, attach, fee + 10000000000L, ts) From a01c32d09c53991bf55a3e2f7a980cadd409addc Mon Sep 17 00:00:00 2001 From: twwu123 Date: Wed, 4 Aug 2021 11:21:10 +0800 Subject: [PATCH 363/391] Add test for adding and removing liquidity in an uneven pool --- .../vswap/ExecuteVSwapValidDiffTest.scala | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala index 6bb8d91a8..5b7309648 100644 --- a/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/vswap/ExecuteVSwapValidDiffTest.scala @@ -481,4 +481,60 @@ class ExecuteVSwapValidDiffTest extends PropSpec } } } + + val preconditionsAndAddRemoveLiquidity: Gen[(GenesisTransaction, GenesisTransaction, RegisterContractTransaction, + RegisterContractTransaction, RegisterContractTransaction, RegisterContractTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, + ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction, ExecuteContractFunctionTransaction)] = for { + (genesis, genesis2, master, user, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, fee, ts, attach) <- + createABLiquidityTokenAndInitVSwap( + 1000000000000000000L, // totalSupplyA + 100000000, // unityA + 1000000000000000000L, // issueAmountA + 100000000000L, // totalSupplyB + 1000, // unityB + 100000000000L, // issueAmountB + 1000000000000000000L, // liquidiityTotalSupply + 1000, // liquidityUnity + 10, // minimumLiquidity + 1017988017151648L + 73842642848352L, // tokenADepositAmount + 99001450413L + 998444587L) // tokenBDepositAmount + + // set swap -> amountADesired, amountBDesired + setSwap <- setSwapVSwapGen(master, regVSwap.contractId, 73842642848352L, 998444587L, attach, fee + 10000000000L, ts + 10) + + addLiquidity <- addLiquidityVSwapGen(master, regVSwap.contractId, 100000000L, 1350L, 99000000L, 1340L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 11) + + removeLiquidity <- removeLiquidityVSwapGen(master, regVSwap.contractId, 135764305914L, 36821321424176L, 498222293L, ts + 1000000000000L, attach, fee + 10000000000L, ts + 12) + + } yield (genesis, genesis2, regTokenA, regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, + depositB, depositLiquidity, setSwap, addLiquidity, removeLiquidity) + + property("vswap test add liquidity to uneven pool") { + forAll(preconditionsAndAddRemoveLiquidity) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, addLiquidity: ExecuteContractFunctionTransaction, _) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(addLiquidity.timestamp, Seq(addLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + } + } + } + + property("vswap test remove liquidity from uneven pool") { + forAll(preconditionsAndAddRemoveLiquidity) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, regTokenA: RegisterContractTransaction, + regTokenB: RegisterContractTransaction, regLiquidity: RegisterContractTransaction, regVSwap: RegisterContractTransaction, issueTokenA: ExecuteContractFunctionTransaction, + issueTokenB: ExecuteContractFunctionTransaction, issueLiquidity: ExecuteContractFunctionTransaction, depositA: ExecuteContractFunctionTransaction, depositB: ExecuteContractFunctionTransaction, + depositLiquidity: ExecuteContractFunctionTransaction, setSwap: ExecuteContractFunctionTransaction, _, removeLiquidity: ExecuteContractFunctionTransaction) => + assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(regTokenA.timestamp, Seq(regTokenA, + regTokenB, regLiquidity, regVSwap, issueTokenA, issueTokenB, issueLiquidity, depositA, depositB, depositLiquidity, setSwap))), + TestBlock.createWithTxStatus(removeLiquidity.timestamp, Seq(removeLiquidity), TransactionStatus.Success)) { (blockDiff, newState) => + blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success + + } + } + } } \ No newline at end of file From a4d63fd4810ad3b1f31e0847cc16442d9cc3521f Mon Sep 17 00:00:00 2001 From: ncying <38449461+ncying@users.noreply.github.com> Date: Fri, 9 Jul 2021 11:24:48 +0800 Subject: [PATCH 364/391] update workflows --- .github/workflows/build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b6eb75b0f..98c300f49 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,10 +10,11 @@ jobs: steps: - name: install scala run: | - echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823 + echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list + echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list + curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add sudo apt-get update - sudo apt-get install -y sbt + sudo apt-get install sbt - uses: actions/checkout@v2 From 395e97acc957dd0d4fb7f127df4b130f88023997 Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 9 Aug 2021 11:13:25 +0800 Subject: [PATCH 365/391] update version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3a4397c6f..aa70fcfe3 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ enablePlugins(sbtdocker.DockerPlugin, JavaServerAppPackaging, JDebPackaging, Sys name := "vsys" organization := "systems.v" -version := "0.3.2" +version := "0.4.0" scalaVersion in ThisBuild := "2.12.6" crossPaths := false publishArtifact in (Compile, packageDoc) := false From fdb180a38b43942232f4d912e4b83090a3d7b87f Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 9 Aug 2021 11:17:57 +0800 Subject: [PATCH 366/391] update max msg length --- src/main/scala/vsys/network/BasicMessagesRepo.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/network/BasicMessagesRepo.scala b/src/main/scala/vsys/network/BasicMessagesRepo.scala index 002895752..7fddb0fbb 100755 --- a/src/main/scala/vsys/network/BasicMessagesRepo.scala +++ b/src/main/scala/vsys/network/BasicMessagesRepo.scala @@ -202,7 +202,7 @@ object TransactionMessageSpec extends MessageSpec[Transaction] { override val messageName: String = "Transaction message" - override val maxLength = 4096 + override val maxLength = 8192 override def deserializeData(bytes: Array[Byte]): Try[Transaction] = TransactionParser.parseBytes(bytes) From 03820012a73373ae7728cac84b7285d433441c55 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Tue, 10 Aug 2021 11:00:10 +0800 Subject: [PATCH 367/391] change name of property test for insufficient balance in atomic swap lock --- .../state/contract/swap/AtomicSwapContractInvalidDiffTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala index fb051a729..5739b1c99 100644 --- a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractInvalidDiffTest.scala @@ -78,7 +78,7 @@ class AtomicSwapContractInvalidDiffTest extends PropSpec lock <- lockAtomicSwapContractDataStackGen(user, regContract.contractId, lockData, lockType, attach, fee, ts + 3) } yield (genesis, genesis2, regContract, depositVSYS, lock, ts, fee) - property("wrong address cannot lock contract") { + property("insufficient balance cannot lock contract") { forAll(preconditionsAndAtomicSwapLockWrongAddressInvalidTest) { case (genesis: GenesisTransaction, genesis2: GenesisTransaction, reg: RegisterContractTransaction, deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit))), From 74d169cf483606833cd56b2a7c8cbca7c3366f8d Mon Sep 17 00:00:00 2001 From: twwu123 Date: Wed, 11 Aug 2021 16:03:35 +0800 Subject: [PATCH 368/391] update data entry type gen in atomic swap --- .../blockchain/contract/swap/AtomicSwapContractGen.scala | 6 +++--- .../state/contract/swap/AtomicSwapContractDiffTest.scala | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala b/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala index d7d07b6dd..dc5f87ac4 100644 --- a/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala +++ b/src/test/scala/vsys/blockchain/contract/swap/AtomicSwapContractGen.scala @@ -32,7 +32,7 @@ trait AtomicSwapContractGen extends SystemContractGen description: String, fee: Long, ts: Long): Gen[RegisterContractTransaction] = RegisterContractTransaction.create(signer, contract, dataStack, description, fee, feeScale, ts).explicitGet() - def lockAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def lockAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = lockIndex for { @@ -40,7 +40,7 @@ trait AtomicSwapContractGen extends SystemContractGen } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def solvePuzzleAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def solvePuzzleAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = solvePuzzleIndex for { @@ -48,7 +48,7 @@ trait AtomicSwapContractGen extends SystemContractGen } yield ExecuteContractFunctionTransaction.create(signer, contractId, id, data, attachment, fee, feeScale, ts).explicitGet() } - def expireWithdrawAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.Value], + def expireWithdrawAtomicSwapContractDataStackGen(signer: PrivateKeyAccount, contractId: ContractAccount, data: Seq[Array[Byte]], dataType: Seq[DataType.DataTypeVal[_]], attachment: Array[Byte], fee: Long, ts: Long): Gen[ExecuteContractFunctionTransaction] = { val id: Short = expireWithdrawIndex for { diff --git a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala index 5c54a7dfb..0f6d7ed8c 100644 --- a/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/contract/swap/AtomicSwapContractDiffTest.scala @@ -195,7 +195,7 @@ class AtomicSwapContractDiffTest extends PropSpec deposit: ExecuteContractFunctionTransaction, lock: ExecuteContractFunctionTransaction, withdraw: ExecuteContractFunctionTransaction, withdrawVSYS: ExecuteContractFunctionTransaction, ts: Long, fee: Long) => assertDiffAndStateCorrectBlockTime(Seq(TestBlock.create(genesis.timestamp, Seq(genesis, genesis2)), TestBlock.create(deposit.timestamp, Seq(reg, deposit))), - TestBlock.create(lock.timestamp + 101, Seq(lock, withdraw, withdrawVSYS))) { (blockDiff, newState) => + TestBlock.create(lock.timestamp + 110, Seq(lock, withdraw, withdrawVSYS))) { (blockDiff, newState) => blockDiff.txsDiff.txStatus shouldBe TransactionStatus.Success val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiff.txsDiff.portfolios.values) totalPortfolioDiff.balance shouldBe -3 * fee From bb9b488d737f8644f041697887fe86deebb8c18c Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 27 Aug 2021 01:52:43 +0700 Subject: [PATCH 369/391] Update vsys-testnet.conf Bring seed nodes up to date. --- vsys-testnet.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsys-testnet.conf b/vsys-testnet.conf index 4946f0e34..31e3f3ff6 100644 --- a/vsys-testnet.conf +++ b/vsys-testnet.conf @@ -3,7 +3,7 @@ vsys { #data-directory = 'your local path' logging-level = DEBUG network { - known-peers = ["54.193.47.112:9923","13.56.200.72:9923","18.218.106.1:9923","3.17.78.253:9923","34.222.191.174:9923"] + known-peers = ["217.79.189.235:9921","163.172.40.33:9921","51.15.190.90:9921","34.238.24.100:9921","44.233.5.150:9921"] black-list-residence-time = 30s peers-broadcast-interval = 5s connection-timeout = 30s From c8d88cf689292eb1a2c2fbec35f6b9b931a2e7f4 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 27 Aug 2021 16:33:53 +0700 Subject: [PATCH 370/391] Update vsys-testnet.conf log level info --- vsys-testnet.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsys-testnet.conf b/vsys-testnet.conf index 31e3f3ff6..6051ab41c 100644 --- a/vsys-testnet.conf +++ b/vsys-testnet.conf @@ -1,7 +1,7 @@ vsys { #directory = 'your local path' #data-directory = 'your local path' - logging-level = DEBUG + logging-level = INFO network { known-peers = ["217.79.189.235:9921","163.172.40.33:9921","51.15.190.90:9921","34.238.24.100:9921","44.233.5.150:9921"] black-list-residence-time = 30s From 2fc208212b41fabbe961f35ec84fad82e4b472bf Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 27 Aug 2021 16:54:53 +0700 Subject: [PATCH 371/391] Update vsys-testnet.conf --- vsys-testnet.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsys-testnet.conf b/vsys-testnet.conf index 6051ab41c..0b30aa422 100644 --- a/vsys-testnet.conf +++ b/vsys-testnet.conf @@ -3,7 +3,7 @@ vsys { #data-directory = 'your local path' logging-level = INFO network { - known-peers = ["217.79.189.235:9921","163.172.40.33:9921","51.15.190.90:9921","34.238.24.100:9921","44.233.5.150:9921"] + known-peers = ["gemmer.vcoin.systems:9923","vnode.vcoin.systems:9923","gemmer.vos.systems:9923","vnode.vos.systems:9923",] black-list-residence-time = 30s peers-broadcast-interval = 5s connection-timeout = 30s From 264985de3975b180f0eb58d67cb0fce12195b951 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 23 Sep 2021 11:48:37 +0800 Subject: [PATCH 372/391] add testnet Riemann activate height --- src/main/scala/vsys/settings/BlockchainSettings.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/settings/BlockchainSettings.scala b/src/main/scala/vsys/settings/BlockchainSettings.scala index 336e1a748..fa3422d44 100644 --- a/src/main/scala/vsys/settings/BlockchainSettings.scala +++ b/src/main/scala/vsys/settings/BlockchainSettings.scala @@ -28,7 +28,7 @@ object FunctionalitySettings { //set the value allowContractTransactionAfterHeight = 4236000, allowDepositWithdrawContractAfterHeight = 12550000, - allowExchangeContractAfterHeight = Int.MaxValue) + allowExchangeContractAfterHeight = 18030000) val configPath = "vsys.blockchain.custom.functionality" } From 154b9f99dd343e9970ab31a74ac4883f35d2bc75 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 23 Sep 2021 11:49:18 +0800 Subject: [PATCH 373/391] update related testnet for testnet Riemann activate height --- .../scala/vsys/settings/BlockchainSettingsSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala index 169322d64..a5aab69f0 100644 --- a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala +++ b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala @@ -99,7 +99,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { settings.functionalitySettings.mintingSpeed should be (1) settings.functionalitySettings.allowContractTransactionAfterHeight should be (4236000) // same as the setting settings.functionalitySettings.allowDepositWithdrawContractAfterHeight should be (12550000) - settings.functionalitySettings.allowExchangeContractAfterHeight should be (Int.MaxValue) + settings.functionalitySettings.allowExchangeContractAfterHeight should be (18030000) settings.genesisSettings.blockTimestamp should be(1535356447650226656L) settings.genesisSettings.timestamp should be(1535356447650226656L) settings.genesisSettings.averageBlockDelay should be(60.seconds) From 266f6f4f3b1a3b21acabc7a61d17045a1b589264 Mon Sep 17 00:00:00 2001 From: Julianxa <46878642+Julianxa@users.noreply.github.com> Date: Tue, 5 Oct 2021 18:02:02 +0800 Subject: [PATCH 374/391] Add an operation in allSlotsInfo --- src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala b/src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala index 93fbf4d59..8f534e72d 100755 --- a/src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala +++ b/src/main/scala/vsys/api/http/spos/SposConsensusApiRoute.scala @@ -62,6 +62,7 @@ case class SposConsensusApiRoute( } @Path("/allSlotsInfo") + @ApiOperation(value = "Get all slots' info", notes = "Get all slots' information", httpMethod = "GET") @ApiResponses(Array( new ApiResponse(code = 200, message = "Json response of all slots details or error") )) From 4684bc8f70982a42143af24c1c0744ee2089db3e Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 22 Oct 2021 11:43:01 +0800 Subject: [PATCH 375/391] fix tx api response --- src/main/scala/vsys/api/http/TransactionsApiRoute.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala index 84e7eea40..794bc6cc9 100644 --- a/src/main/scala/vsys/api/http/TransactionsApiRoute.scala +++ b/src/main/scala/vsys/api/http/TransactionsApiRoute.scala @@ -47,7 +47,8 @@ case class TransactionsApiRoute( @Path("/count") @ApiOperation(value = "Count", notes = "Get count of transactions where specified address (wallet address or contract address) has been involved. *This is a custom api, you need to enable it in configuration file.*", - httpMethod = "GET") + httpMethod = "GET", + response = classOf[Int]) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Wallet address or contract address", required = true, dataType = "string", paramType = "query"), new ApiImplicitParam(name = "txType", value = "Transaction type", required = false, dataType = "integer", paramType = "query") @@ -86,6 +87,9 @@ case class TransactionsApiRoute( @ApiOperation(value = "List", notes = "Get list of transactions where specified address (wallet address or contract address) has been involved. *This is a custom api, you need to enable it in configuration file.*", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response with a list of transactions or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Wallet address or contract address", required = true, dataType = "string", paramType = "query"), new ApiImplicitParam(name = "txType", value = "Transaction type", required = false, dataType = "integer", paramType = "query"), @@ -130,6 +134,9 @@ case class TransactionsApiRoute( @Path("/address/{address}/limit/{limit}") @ApiOperation(value = "Address", notes = "Get list of transactions where specified address (wallet address or contract address) has been involved", httpMethod = "GET") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response with a list of transactions or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "address", value = "Wallet address or contract address", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "limit", value = "Specified number of records to be returned", required = true, dataType = "integer", paramType = "path") From 0616b28b04d011792983ccd78510f2b7f4e29efb Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 22 Oct 2021 11:43:31 +0800 Subject: [PATCH 376/391] fix contract api response --- .../vsys/api/http/contract/ContractApiRoute.scala | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index f38f4aaae..ffc0ca224 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -76,6 +76,9 @@ case class ContractApiRoute (settings: RestAPISettings, @Path("/lastTokenIndex/{contractId}") @ApiOperation(value = "Last Token Index", notes = "Token contract last token index", httpMethod = "Get") + @ApiResponses(Array( + new ApiResponse(code = 200, message = "Json response with Last Token Index or error") + )) @ApiImplicitParams(Array( new ApiImplicitParam(name = "contractId", value = "Contract ID", required = true, dataType = "string", paramType = "path") )) @@ -86,10 +89,7 @@ case class ContractApiRoute (settings: RestAPISettings, if (lastTokenIndex == -1) { complete(CustomValidationError("No token generated in this contract")) } else { - complete(Json.obj( - "contractId" -> contractId, - "lastTokenIndex" -> lastTokenIndex - )) + complete(TokenIndex(contractId, lastTokenIndex)) } } case _ => complete(InvalidContractAddress) @@ -343,4 +343,8 @@ object ContractApiRoute { implicit val balanceFormat: Format[Balance] = Json.format + case class TokenIndex(contractId: String, lastTokenIndex: Int) + + implicit val tokenIndexFormat: Format[TokenIndex] = Json.format + } \ No newline at end of file From 39c1208b2a30aa922c173ff9ca97ccac35bfc661 Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 22 Oct 2021 11:43:54 +0800 Subject: [PATCH 377/391] fix swagger doc service --- .../scala/vsys/api/http/swagger/SwaggerDocService.scala | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vsys/api/http/swagger/SwaggerDocService.scala b/src/main/scala/vsys/api/http/swagger/SwaggerDocService.scala index 8311c0d86..dd4796393 100755 --- a/src/main/scala/vsys/api/http/swagger/SwaggerDocService.scala +++ b/src/main/scala/vsys/api/http/swagger/SwaggerDocService.scala @@ -7,11 +7,11 @@ import com.github.swagger.akka.SwaggerHttpService import vsys.Version import vsys.settings.RestAPISettings import io.swagger.util.{Json, Yaml} -import io.swagger.models.{Swagger, Scheme, Path} +import io.swagger.models.{Path, Scheme, Swagger} import io.swagger.models.auth.{ApiKeyAuthDefinition, In} import vsys.utils.ScorexLogging -import scala.collection.immutable.Map +import scala.collection.immutable.Map import scala.util.control.NonFatal import scala.collection.JavaConverters._ @@ -59,11 +59,6 @@ class SwaggerDocService(val actorSystem: ActorSystem, val materializer: ActorMat val filteredPaths: Map[String, Path] = swagger.getPaths().asScala.toMap.filterKeys(cumstomPathsConfig.getOrElse(_, true)) swagger.addSecurityDefinition("api_key", new ApiKeyAuthDefinition("api_key", In.HEADER)) swagger.paths(collection.mutable.Map(filteredPaths.toSeq: _*).asJava) - val unwantedDefinitions: Seq[String] = Seq("Function1", "Function1RequestContextFutureRouteResult") - if (unwantedDefinitions.nonEmpty) { - swagger.setDefinitions(swagger.getDefinitions.asScala.filterKeys(definitionName => !unwantedDefinitions.contains(definitionName)).asJava) - } - swagger } //Let swagger-ui determine the host and port From aa0871854cf88153acd5bb263d3cd4bda4047d4e Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 8 Nov 2021 11:54:30 +0800 Subject: [PATCH 378/391] fix v swap textual issue --- .../vsys/blockchain/contract/ContractVSwap.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala index 9dcea88e7..a354e4293 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVSwap.scala @@ -199,13 +199,13 @@ object ContractVSwap { assertTrue ++ Array(19.toByte), cdbvMapValMinus ++ Array(liquidityBalanceMap.index, 2.toByte, 18.toByte), cdbvMapValAdd ++ Array(liquidityBalanceMap.index, 2.toByte, 17.toByte), - basicMinus ++ Array(18.toByte, 14.toByte, 19.toByte), - cdbvStateValAdd ++ Array(liquidityTokenLeftStateVar.index, 19.toByte), + basicMinus ++ Array(18.toByte, 14.toByte, 20.toByte), + cdbvStateValAdd ++ Array(liquidityTokenLeftStateVar.index, 20.toByte), cdbvStateValAdd ++ Array(totalSupplyStateVar.index, 14.toByte), cdbvStateValAdd ++ Array(tokenAReservedStateVar.index, 0.toByte), cdbvStateValAdd ++ Array(tokenBReservedStateVar.index, 1.toByte), - basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(20.toByte), - cdbvSet ++ Array(swapStatusStateVar.index, 20.toByte) + basicConstantGet ++ DataEntry(Array(1.toByte), DataType.Boolean).bytes ++ Array(21.toByte), + cdbvSet ++ Array(swapStatusStateVar.index, 21.toByte) ) lazy val setSwapFunc: Array[Byte] = getFunctionBytes(setSwapId, publicFuncType, nonReturnType, setSwapDataType, setSwapFunctionOpcs) val setSwapTextualBytes: Array[Byte] = textualFunc("setSwap", Seq(), setSwapPara) @@ -427,7 +427,7 @@ object ContractVSwap { basicMinus ++ Array(13.toByte, 21.toByte, 25.toByte), basicMultiply ++ Array(25.toByte, 17.toByte, 26.toByte), basicAdd ++ Array(18.toByte, 16.toByte, 27.toByte)) ++ - swapKValueCheck(26.toByte, 27.toByte, 15.toByte, 13.toByte, 14.toByte, 28.toByte) ++ Seq( + swapKValueCheck(26.toByte, 27.toByte, 17.toByte, 13.toByte, 14.toByte, 28.toByte) ++ Seq( cdbvStateValMinus ++ Array(tokenAReservedStateVar.index, 23.toByte), cdbvMapValMinus ++ Array(tokenBBalanceMap.index, 3.toByte, 1.toByte), cdbvStateValAdd ++ Array(tokenBReservedStateVar.index, 1.toByte), @@ -498,7 +498,7 @@ object ContractVSwap { basicMinus ++ Array(14.toByte, 21.toByte, 25.toByte), basicMultiply ++ Array(25.toByte, 17.toByte, 26.toByte), basicAdd ++ Array(18.toByte, 16.toByte, 27.toByte)) ++ - swapKValueCheck(27.toByte, 26.toByte, 15.toByte, 13.toByte, 14.toByte, 28.toByte) ++ Seq( + swapKValueCheck(27.toByte, 26.toByte, 17.toByte, 13.toByte, 14.toByte, 28.toByte) ++ Seq( cdbvStateValMinus ++ Array(tokenBReservedStateVar.index, 23.toByte), cdbvMapValMinus ++ Array(tokenABalanceMap.index, 3.toByte, 1.toByte), cdbvStateValAdd ++ Array(tokenAReservedStateVar.index, 1.toByte), From 0f80e0887576b14c0a0891953ab18a10c0ddab25 Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 8 Nov 2021 11:56:05 +0800 Subject: [PATCH 379/391] fix v stable swap textual issue --- .../scala/vsys/blockchain/contract/ContractVStableSwap.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala index 0a8929159..f75c914e4 100644 --- a/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala +++ b/src/main/scala/vsys/blockchain/contract/ContractVStableSwap.scala @@ -125,7 +125,7 @@ object ContractVStableSwap { val withdrawId: Short = 2 val withdrawPara: Seq[String] = Seq("withdrawer", "amount", "tokenId") ++ Seq("baseTokenId", "targetTokenId", "isValidTokenId", - "isBaseToken", "valueFalse", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock") + "isBaseToken", "baseTokenIfBlock", "isTargetToken", "targetTokenIfBlock") val withdrawDataType: Array[Byte] = Array(DataType.Address.id.toByte, DataType.Amount.id.toByte, DataType.TokenId.id.toByte) val withdrawTriggerOpcs: Seq[Array[Byte]] = Seq( assertCaller ++ Array(0.toByte), From 9a857b144571add6a03f83898b8e341d4c2f3774 Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 8 Nov 2021 11:57:12 +0800 Subject: [PATCH 380/391] add basic opc unit test --- .../vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala | 2 +- .../vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala index 3e36fcb47..eb5e283f9 100644 --- a/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala +++ b/src/main/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiff.scala @@ -157,7 +157,7 @@ object BasicOpcDiff extends OpcDiffer { private def formatResB[T] (res: Array[Byte], dt: DataTypeVal[T]): Either[ValidationError, DataEntry] = DataEntry.create(res, dt).left.map(_ => ValidationError.OverflowError) - def differ(bytes: Array[Byte], data: Seq[DataEntry], t: BasicType.BasicTypeVal) = updateStack(data, bytes.last, t.op(bytes, data)) + def differ(bytes: Array[Byte], data: Seq[DataEntry], t: BasicType.BasicTypeVal): Either[ValidationError, Seq[DataEntry]] = updateStack(data, bytes.last, t.op(bytes, data)) override def parseBytesDt(context: ExecutionContext)(bytes: Array[Byte], data: Seq[DataEntry]): Either[ValidationError, Seq[DataEntry]] = bytes.headOption.flatMap(f => Try(BasicType(f)).toOption) match { diff --git a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala index 3e6356baa..69fe4fd11 100644 --- a/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala +++ b/src/test/scala/vsys/blockchain/state/opcdiffs/BasicOpcDiffTest.scala @@ -44,6 +44,14 @@ class BasicOpcDiffTest extends PropSpec with PropertyChecks with GeneratorDriven DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Amount), BasicOpcDiff.minus) should be (Right(DataEntry(Longs.toByteArray(0), DataType.Amount))) + BasicOpcDiff.numBiOperation( + DataEntry(Longs.toByteArray(1), DataType.Amount), + DataEntry(Longs.toByteArray(2), DataType.Amount), + BasicOpcDiff.minus) should be (Left(ValidationError.OverflowError)) + BasicOpcDiff.numBiOperation( + DataEntry(DataType.arrayShortLengthToByteArray(BigInt(1).toByteArray) ++ BigInt(1).toByteArray, DataType.BigInteger), + DataEntry(DataType.arrayShortLengthToByteArray(BigInt(2).toByteArray) ++ BigInt(2).toByteArray, DataType.BigInteger), + BasicOpcDiff.minus) should be (Right(DataEntry(DataType.arrayShortLengthToByteArray(BigInt(-1).toByteArray) ++ BigInt(-1).toByteArray, DataType.BigInteger))) BasicOpcDiff.numBiOperation( DataEntry(Longs.toByteArray(1), DataType.Amount), DataEntry(Longs.toByteArray(1), DataType.Timestamp), From 3e85ad5fe798e2f68cefba3935e8ce0ff1a149eb Mon Sep 17 00:00:00 2001 From: ncying Date: Mon, 8 Nov 2021 11:57:34 +0800 Subject: [PATCH 381/391] update contract translator --- src/test/scala/tools/ContractTranslator.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/scala/tools/ContractTranslator.scala b/src/test/scala/tools/ContractTranslator.scala index 9f8d9080d..9bfb1b61d 100644 --- a/src/test/scala/tools/ContractTranslator.scala +++ b/src/test/scala/tools/ContractTranslator.scala @@ -375,6 +375,7 @@ object ContractTranslator extends App { case opcType: Byte if opcType == CompareType.Ge.id => nameList(data(4)) + " = operation.compare.greaterEqual(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case opcType: Byte if opcType == CompareType.Gt.id => nameList(data(4)) + " = operation.compare.greater(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case opcType: Byte if opcType == CompareType.Beq.id => nameList(data(4)) + " = operation.compare.bytesEqual(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == CompareType.Le.id => nameList(data(4)) + " = operation.compare.lessEqual(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case _ => "--- invalid opc code ---" } @@ -390,6 +391,7 @@ object ContractTranslator extends App { case opcType: Byte if opcType == BasicType.Convert.id => nameList(data(4)) + " = operation.basic.convert(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case opcType: Byte if opcType == BasicType.ConstantGet.id => nameList(data.last) + " = operation.basic.getConstant(" + strDataEntry(data.slice(2, data.length - 1), nameList) + ")" case opcType: Byte if opcType == BasicType.SqrtBigInt.id => nameList(data(3)) + " = operation.basic.sqrt(" + nameList(data(2)) + ")" + case opcType: Byte if opcType == BasicType.And.id => nameList(data(4)) + " = operation.basic.and(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case _ => "--- invalid opc code ---" } case opcType: Byte if opcType == OpcType.IfOpc.id => From 47519e4f6ff460c0b9d54dcfef6c58fc4a2f90f6 Mon Sep 17 00:00:00 2001 From: xysing6 <93632259+xysing6@users.noreply.github.com> Date: Wed, 17 Nov 2021 17:45:53 +0800 Subject: [PATCH 382/391] Update PeerInfo.scala fix:change peers connect api Modify the default request parameters --- src/main/scala/vsys/network/PeerInfo.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vsys/network/PeerInfo.scala b/src/main/scala/vsys/network/PeerInfo.scala index ebb970f2c..ba1c7946f 100644 --- a/src/main/scala/vsys/network/PeerInfo.scala +++ b/src/main/scala/vsys/network/PeerInfo.scala @@ -4,7 +4,7 @@ import java.net.InetSocketAddress import io.swagger.annotations._ case class PeerNetworkConnection(@ApiModelProperty(required = true, example = "127.0.0.1") - address: String, + host: String, @ApiModelProperty(required = true, example = "0") port: Int) From d2a94dd45f4ba525140912b5752ea17913b5c195 Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 17 Nov 2021 19:00:19 +0800 Subject: [PATCH 383/391] update contract translator --- src/test/scala/tools/ContractTranslator.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/scala/tools/ContractTranslator.scala b/src/test/scala/tools/ContractTranslator.scala index 9bfb1b61d..3f166fae4 100644 --- a/src/test/scala/tools/ContractTranslator.scala +++ b/src/test/scala/tools/ContractTranslator.scala @@ -356,8 +356,8 @@ object ContractTranslator extends App { case opcType: Byte if opcType == OpcType.TDBAOpc.id => y match { - case opcType: Byte if opcType == TDBAType.DepositTDBA.id => "operation.token.deposit(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" - case opcType: Byte if opcType == TDBAType.WithdrawTDBA.id => "operation.token.withdraw(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == TDBAType.DepositTDBA.id => "operation.token.issue(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" + case opcType: Byte if opcType == TDBAType.WithdrawTDBA.id => "operation.token.brun(" + nameList(data(2)) + ", " + nameList(data(3)) + ")" case opcType: Byte if opcType == TDBAType.TransferTDBA.id => "operation.token.transfer(" + nameList(data(2)) + ", " + nameList(data(3)) + ", " + nameList(data(4)) + ")" case _ => "--- invalid opc code ---" } From 9af6c91761c621056c94ca062614536add1098c0 Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 30 Nov 2021 12:29:03 +0800 Subject: [PATCH 384/391] add last token index path --- .../vsys/api/http/contract/ContractApiRoute.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala index ffc0ca224..57814033c 100644 --- a/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala +++ b/src/main/scala/vsys/api/http/contract/ContractApiRoute.scala @@ -36,7 +36,7 @@ case class ContractApiRoute (settings: RestAPISettings, extends ApiRoute with BroadcastRoute { override val route = pathPrefix("contract") { - register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData + register ~ content ~ info ~ tokenInfo ~ balance ~ execute ~ tokenId ~ vBalance ~ getContractData ~ lastToken } @Path("/register") @@ -115,7 +115,7 @@ case class ContractApiRoute (settings: RestAPISettings, } } - @Path("data/{contractId}/{key}") + @Path("/data/{contractId}/{key}") @ApiOperation(value = "Contract Data", notes = "Get **contract data** by given `contractId` and `key` (default numerical 0).", httpMethod = "Get", authorizations = Array(new Authorization("api_key"))) @ApiResponses(Array( new ApiResponse(code = 200, message = "Json response of contract data or error") @@ -124,7 +124,7 @@ case class ContractApiRoute (settings: RestAPISettings, new ApiImplicitParam(name = "contractId", value = "Contract Account", required = true, dataType = "string", paramType = "path"), new ApiImplicitParam(name = "key", value = "Key", required = true, dataType = "string", paramType = "path") )) - def getContractData: Route = (get & withAuth & path("data" / Segment / Segment)) { (contractId, key) => + def getContractData: Route = (get & path("data" / Segment / Segment)) { (contractId, key) => complete(dataJson(contractId, key)) } @@ -225,7 +225,7 @@ case class ContractApiRoute (settings: RestAPISettings, } } - @Path("balance/{address}/{tokenId}") + @Path("/balance/{address}/{tokenId}") @ApiOperation(value = "Token's balance", notes = "Get the **balance** of a specified `tokenId` by a given `address`", httpMethod = "Get") @ApiResponses(Array( new ApiResponse(code = 200, message = "Json response of the token balance or error") @@ -302,7 +302,7 @@ case class ContractApiRoute (settings: RestAPISettings, @ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Operation"))) def execute: Route = processRequest("execute", (t: ExecuteContractFunctionRequest) => doBroadcast(TransactionFactory.executeContractFunction(t, wallet, time))) - @Path("contractId/{contractId}/tokenIndex/{tokenIndex}") + @Path("/contractId/{contractId}/tokenIndex/{tokenIndex}") @ApiResponses(Array( new ApiResponse(code = 200, message = "Json response of a token id or error") )) From 89d6222a03c1503a67744ae0626b3f760bdc5dfd Mon Sep 17 00:00:00 2001 From: ncying Date: Tue, 30 Nov 2021 12:29:48 +0800 Subject: [PATCH 385/391] add port to testnet conf --- vsys-testnet.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/vsys-testnet.conf b/vsys-testnet.conf index 0b30aa422..917f00efb 100644 --- a/vsys-testnet.conf +++ b/vsys-testnet.conf @@ -7,6 +7,7 @@ vsys { black-list-residence-time = 30s peers-broadcast-interval = 5s connection-timeout = 30s + port = 9923 } wallet { password = "" From 01f9f9c2787750b9382b0f98794e5830265c40dc Mon Sep 17 00:00:00 2001 From: ncying Date: Wed, 1 Dec 2021 10:15:38 +0800 Subject: [PATCH 386/391] update version to 0.4.1 and add mainnet activate height --- build.sbt | 2 +- src/main/scala/vsys/settings/BlockchainSettings.scala | 2 +- .../scala/vsys/settings/BlockchainSettingsSpecification.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index aa70fcfe3..74bd2394d 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ enablePlugins(sbtdocker.DockerPlugin, JavaServerAppPackaging, JDebPackaging, Sys name := "vsys" organization := "systems.v" -version := "0.4.0" +version := "0.4.1" scalaVersion in ThisBuild := "2.12.6" crossPaths := false publishArtifact in (Compile, packageDoc) := false diff --git a/src/main/scala/vsys/settings/BlockchainSettings.scala b/src/main/scala/vsys/settings/BlockchainSettings.scala index fa3422d44..21f7cbfed 100644 --- a/src/main/scala/vsys/settings/BlockchainSettings.scala +++ b/src/main/scala/vsys/settings/BlockchainSettings.scala @@ -19,7 +19,7 @@ object FunctionalitySettings { //set the value allowContractTransactionAfterHeight = 6100000, allowDepositWithdrawContractAfterHeight = 13140520, - allowExchangeContractAfterHeight = Int.MaxValue) + allowExchangeContractAfterHeight = 24400000) val TESTNET = FunctionalitySettings( numOfSlots = 60, diff --git a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala index a5aab69f0..9938baf19 100644 --- a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala +++ b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala @@ -142,7 +142,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { settings.functionalitySettings.mintingSpeed should be (1) settings.functionalitySettings.allowContractTransactionAfterHeight should be (6100000) // same as the setting settings.functionalitySettings.allowDepositWithdrawContractAfterHeight should be (13140520) - settings.functionalitySettings.allowExchangeContractAfterHeight should be (Int.MaxValue) + settings.functionalitySettings.allowExchangeContractAfterHeight should be (24400000) settings.genesisSettings.blockTimestamp should be(1543286357457333127L) settings.genesisSettings.timestamp should be(1543286357457333127L) settings.genesisSettings.signature should be(ByteStr.decodeBase58("3yYNd7quEWaWytrAug4yGwQvpL3PVJegf9d9NTv9PVE3ouBYJs5PTQqxCjd294uK1zPLj6G5Tk447LqFMWdSFvaQ").toOption) From 668568b94b090bf0e2d294e2b9d9b9aa014e4d1b Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 17 Dec 2021 11:00:01 +0800 Subject: [PATCH 387/391] update activate height --- src/main/scala/vsys/settings/BlockchainSettings.scala | 2 +- src/test/scala/tools/ContractTranslator.scala | 2 +- .../scala/vsys/settings/BlockchainSettingsSpecification.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vsys/settings/BlockchainSettings.scala b/src/main/scala/vsys/settings/BlockchainSettings.scala index 21f7cbfed..1d83ceff0 100644 --- a/src/main/scala/vsys/settings/BlockchainSettings.scala +++ b/src/main/scala/vsys/settings/BlockchainSettings.scala @@ -19,7 +19,7 @@ object FunctionalitySettings { //set the value allowContractTransactionAfterHeight = 6100000, allowDepositWithdrawContractAfterHeight = 13140520, - allowExchangeContractAfterHeight = 24400000) + allowExchangeContractAfterHeight = 24724000) val TESTNET = FunctionalitySettings( numOfSlots = 60, diff --git a/src/test/scala/tools/ContractTranslator.scala b/src/test/scala/tools/ContractTranslator.scala index 3f166fae4..9d3db340f 100644 --- a/src/test/scala/tools/ContractTranslator.scala +++ b/src/test/scala/tools/ContractTranslator.scala @@ -22,7 +22,7 @@ import vsys.utils.serialization.Deser import scala.util.{Failure, Success, Try} object ContractTranslator extends App { - val bytes = ContractVOption.contract.bytes.arr + val bytes = ContractVStableSwap.contract.bytes.arr val showHex = false println(Base58.encode(bytes)) diff --git a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala index 9938baf19..16ef55d54 100644 --- a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala +++ b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala @@ -142,7 +142,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { settings.functionalitySettings.mintingSpeed should be (1) settings.functionalitySettings.allowContractTransactionAfterHeight should be (6100000) // same as the setting settings.functionalitySettings.allowDepositWithdrawContractAfterHeight should be (13140520) - settings.functionalitySettings.allowExchangeContractAfterHeight should be (24400000) + settings.functionalitySettings.allowExchangeContractAfterHeight should be (24724000) settings.genesisSettings.blockTimestamp should be(1543286357457333127L) settings.genesisSettings.timestamp should be(1543286357457333127L) settings.genesisSettings.signature should be(ByteStr.decodeBase58("3yYNd7quEWaWytrAug4yGwQvpL3PVJegf9d9NTv9PVE3ouBYJs5PTQqxCjd294uK1zPLj6G5Tk447LqFMWdSFvaQ").toOption) From 563bcecf238a56d5d2acd03e6ce0e2db54e5e927 Mon Sep 17 00:00:00 2001 From: Min Jong Kim Date: Mon, 20 Dec 2021 17:38:38 +0900 Subject: [PATCH 388/391] Logback Version 1.2.9 Update Due to CVE-2021-42550 Vulnerability --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index b026e79e5..def828fa7 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -46,7 +46,7 @@ object Dependencies { ) lazy val logging = Seq( - "ch.qos.logback" % "logback-classic" % "1.2.3", + "ch.qos.logback" % "logback-classic" % "1.2.9", "org.slf4j" % "slf4j-api" % "1.7.25", "org.slf4j" % "jul-to-slf4j" % "1.7.25", "net.logstash.logback" % "logstash-logback-encoder" % "4.11" From c52e2eeb1e918387fd2d4468a4a2397a00d1470d Mon Sep 17 00:00:00 2001 From: ncying Date: Fri, 31 Dec 2021 14:46:26 +0800 Subject: [PATCH 389/391] update version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 74bd2394d..955fd766c 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ enablePlugins(sbtdocker.DockerPlugin, JavaServerAppPackaging, JDebPackaging, Sys name := "vsys" organization := "systems.v" -version := "0.4.1" +version := "0.4.2" scalaVersion in ThisBuild := "2.12.6" crossPaths := false publishArtifact in (Compile, packageDoc) := false From 622620efbf53e932ac858d157c4c69b532435305 Mon Sep 17 00:00:00 2001 From: Zhenqi Liu Date: Fri, 7 Jan 2022 16:13:40 +0800 Subject: [PATCH 390/391] Update typesafe dependencies and version --- build.sbt | 2 +- project/plugins.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index aa70fcfe3..74bd2394d 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ enablePlugins(sbtdocker.DockerPlugin, JavaServerAppPackaging, JDebPackaging, Sys name := "vsys" organization := "systems.v" -version := "0.4.0" +version := "0.4.1" scalaVersion in ThisBuild := "2.12.6" crossPaths := false publishArtifact in (Compile, packageDoc) := false diff --git a/project/plugins.sbt b/project/plugins.sbt index 1df1fb741..3ce620453 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ resolvers ++= Seq( - "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/", + "Typesafe repository" at "https://repo.scala-sbt.org", "Artima Maven Repository" at "https://repo.artima.com/releases", "JBoss" at "https://repository.jboss.org", Resolver.sbtPluginRepo("releases") From 8fbfcb1eaf685e708f7139c333dd72b1091eb937 Mon Sep 17 00:00:00 2001 From: ncying Date: Thu, 20 Jan 2022 16:17:11 +0800 Subject: [PATCH 391/391] update activate info --- src/main/scala/vsys/settings/BlockchainSettings.scala | 2 +- .../scala/vsys/settings/BlockchainSettingsSpecification.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vsys/settings/BlockchainSettings.scala b/src/main/scala/vsys/settings/BlockchainSettings.scala index 1d83ceff0..620432cc6 100644 --- a/src/main/scala/vsys/settings/BlockchainSettings.scala +++ b/src/main/scala/vsys/settings/BlockchainSettings.scala @@ -19,7 +19,7 @@ object FunctionalitySettings { //set the value allowContractTransactionAfterHeight = 6100000, allowDepositWithdrawContractAfterHeight = 13140520, - allowExchangeContractAfterHeight = 24724000) + allowExchangeContractAfterHeight = 25416184) val TESTNET = FunctionalitySettings( numOfSlots = 60, diff --git a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala index 16ef55d54..3fff03863 100644 --- a/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala +++ b/src/test/scala/vsys/settings/BlockchainSettingsSpecification.scala @@ -142,7 +142,7 @@ class BlockchainSettingsSpecification extends FlatSpec with Matchers { settings.functionalitySettings.mintingSpeed should be (1) settings.functionalitySettings.allowContractTransactionAfterHeight should be (6100000) // same as the setting settings.functionalitySettings.allowDepositWithdrawContractAfterHeight should be (13140520) - settings.functionalitySettings.allowExchangeContractAfterHeight should be (24724000) + settings.functionalitySettings.allowExchangeContractAfterHeight should be (25416184) settings.genesisSettings.blockTimestamp should be(1543286357457333127L) settings.genesisSettings.timestamp should be(1543286357457333127L) settings.genesisSettings.signature should be(ByteStr.decodeBase58("3yYNd7quEWaWytrAug4yGwQvpL3PVJegf9d9NTv9PVE3ouBYJs5PTQqxCjd294uK1zPLj6G5Tk447LqFMWdSFvaQ").toOption)