Skip to content

Commit 601b285

Browse files
authored
Merge pull request #197 from virtualeconomy/systemCall
fix style issue also system transfer insufficient vsys issue
2 parents 1d88623 + 13b7f06 commit 601b285

File tree

11 files changed

+43
-23
lines changed

11 files changed

+43
-23
lines changed

src/main/scala/vsys/api/http/contract/ContractApiRoute.scala

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import vsys.blockchain.state.ByteStr
1515
import vsys.blockchain.state.reader.StateReader
1616
import vsys.blockchain.transaction._
1717
import vsys.blockchain.UtxPool
18-
import vsys.blockchain.contract.{ContractDepositWithdraw, ContractPermitted, ContractSystem}
18+
import vsys.blockchain.contract._
1919
import vsys.settings.RestAPISettings
2020
import vsys.utils.serialization.Deser
2121
import vsys.utils.Time
@@ -134,7 +134,11 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx
134134
case ContractPermitted.contract.bytes => "TokenContractWithSplit"
135135
case ContractPermitted.contractWithoutSplit.bytes => "TokenContract"
136136
case ContractDepositWithdraw.contract.bytes => "DepositWithdrawContract"
137+
case ContractDepositWithdrawProductive.contract.bytes => "ProductiveDepositWithdrawContract"
137138
case ContractSystem.contract.bytes => "SystemContract"
139+
case ContractLock.contract.bytes => "LockContract"
140+
case ContractNonFungible.contract.bytes => "NonFungibleContract"
141+
case ContractPaymentChannel.contract.bytes => "PaymentChannelContract"
138142
case _ => "GeneralContract"
139143
}
140144

@@ -193,7 +197,7 @@ case class ContractApiRoute (settings: RestAPISettings, wallet: Wallet, utx: Utx
193197
case Some(x) => (for {
194198
acc <- Account.fromString(address)
195199
} yield Json.obj(
196-
"address/contract" -> acc.bytes.base58,
200+
"address/contractId" -> acc.bytes.base58,
197201
"height" -> height,
198202
"tokenId" -> tokenIdStr,
199203
"balance" -> state.tokenAccountBalance(ByteStr(tokenId.arr ++ acc.bytes.arr)),

src/main/scala/vsys/blockchain/contract/ContractGen.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ object ContractGen {
1717
val loadSigner = Array(2.toByte, 1.toByte)
1818
val loadCaller = Array(2.toByte, 2.toByte)
1919
val loadTimestamp = Array(2.toByte, 3.toByte)
20-
val loadTokenNum = Array(2.toByte, 4.toByte)
20+
val loadLastTokenIndex = Array(2.toByte, 4.toByte)
2121
val loadTransactionId = Array(2.toByte, 5.toByte)
2222
val loadPublicKey = Array(2.toByte, 6.toByte)
2323

src/main/scala/vsys/blockchain/contract/ContractNonFungible.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ object ContractNonFungible {
5555
assertCaller ++ Array(1.toByte),
5656
basicConstantGet ++ DataEntry(Longs.toByteArray(1), DataType.Amount).bytes ++ Array(2.toByte),
5757
tdbNewToken ++ Array(2.toByte, 2.toByte, 0.toByte),
58-
loadTokenNum ++ Array(3.toByte),
58+
loadLastTokenIndex ++ Array(3.toByte),
5959
tdbaDeposit ++ Array(1.toByte, 2.toByte, 3.toByte))
6060
lazy val issueFunc: Array[Byte] = getFunctionBytes(issueId, publicFuncType, nonReturnType, issueDataType, issueOpcs)
6161
val issueFuncBytes: Array[Byte] = textualFunc("issue", Seq(), issuePara)

src/main/scala/vsys/blockchain/state/StateWriter.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class StateWriterImpl(p: StateStorage, synchronizationToken: ReentrantReadWriteL
103103

104104
measureSizeLog("contractNumDB")(blockDiff.txsDiff.contractNumDB) {
105105
_.foreach { case (id, dValue) =>
106-
val updatedNum = contractNumInfo(id) + dValue
106+
val updatedNum = safeSum(contractNumInfo(id), dValue)
107107
sp().contractNumDB.put(id, updatedNum)
108108
}
109109
}

src/main/scala/vsys/blockchain/state/diffs/ExecuteContractFunctionTransactionDiff.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package vsys.blockchain.state.diffs
33
import cats.implicits._
44
import vsys.blockchain.contract.ExecutionContext
55
import vsys.blockchain.state.opcdiffs.OpcFuncDiffer
6-
import vsys.blockchain.state.reader.StateReader
6+
import vsys.blockchain.state.reader.{CompositeStateReader, StateReader}
77
import vsys.blockchain.state.{Diff, LeaseInfo, Portfolio}
88
import vsys.blockchain.transaction.contract.ExecuteContractFunctionTransaction
99
import vsys.blockchain.transaction.{TransactionStatus, ValidationError}
@@ -18,6 +18,8 @@ object ExecuteContractFunctionTransactionDiff {
1818
( for {
1919
exContext <- ExecutionContext.fromExeConTx(s, settings, prevBlockTimestamp, currentBlockTimestamp, height, tx)
2020
diff <- OpcFuncDiffer(exContext)(tx.data)
21+
newState = new CompositeStateReader(s, diff.asBlockDiff(height, tx))
22+
_ <- Either.cond(newState.accountPortfolio(senderAddress).balance >= tx.transactionFee, (), ValidationError.ContractVSYSBalanceInsufficient)
2123
} yield Diff(
2224
height = height,
2325
tx = tx,

src/main/scala/vsys/blockchain/state/opcdiffs/CDBVROpcDiff.scala

+6-10
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,12 @@ object CDBVROpcDiff extends OpcDiffer {
4848
Left(ContractLocalVariableIndexOutOfRange)
4949
} else {
5050
val combinedKey = context.contractId.bytes.arr ++ Array(stateMap(0)) ++ keyValue.bytes
51-
if (DataType(stateMap(2)) == DataType.Amount) { // amount balance map
52-
val getVal = context.state.contractNumInfo(ByteStr(combinedKey))
53-
Right(dataStack.patch(pointer, Seq(DataEntry(Longs.toByteArray(getVal), DataType.Amount)), 1))
54-
} else if (DataType(stateMap(2)) == DataType.Timestamp) { // timestamp
55-
context.state.contractInfo(ByteStr(combinedKey)) match {
56-
case Some(v) => Right(dataStack.patch(pointer, Seq(v), 1))
57-
case _ => Right(dataStack.patch(pointer, Seq(DataEntry(Longs.toByteArray(0L), DataType.Timestamp)), 1))
58-
}
59-
} else {
60-
Left(ContractStateMapNotDefined)
51+
context.state.contractInfo(ByteStr(combinedKey)) match {
52+
case Some(v) => Right(dataStack.patch(pointer, Seq(v), 1))
53+
case _ if (DataType(stateMap(2)) == DataType.Timestamp) => Right(dataStack.patch(pointer, Seq(DataEntry(Longs.toByteArray(0L), DataType.Timestamp)), 1))
54+
case _ if (DataType(stateMap(2)) == DataType.Amount) => Right(dataStack.patch(pointer,
55+
Seq(DataEntry(Longs.toByteArray(context.state.contractNumInfo(ByteStr(combinedKey))), DataType.Amount)), 1))
56+
case _ => Left(ContractStateMapNotDefined)
6157
}
6258
}
6359
}

src/main/scala/vsys/blockchain/state/opcdiffs/OpcDiff.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ object OpcDiff {
3333
tokenDB = d.tokenDB,
3434
tokenAccountBalance = d.tokenAccountBalance,
3535
relatedAddress = d.relatedAddress,
36-
portfolios = d.portfolios
36+
portfolios = d.portfolios
3737
)
3838

3939
def asBlockDiff(height: Int, tx: Transaction): BlockDiff =

src/main/scala/vsys/blockchain/transaction/TransactionStatus.scala

+1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ object TransactionStatus extends Enumeration {
3030
val ContractStateMapNotDefined = Value(27)
3131
val ContractMapValueInsufficient = Value(28)
3232
val ContractInvalidSignature = Value(29)
33+
val ContractVSYSBalanceInsufficient = Value(30)
3334
}

src/main/scala/vsys/blockchain/transaction/ValidationError.scala

+3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ object ValidationError {
104104
case object ContractInvalidSignature extends ContractValidationError {
105105
override val transactionStatus = TransactionStatus.ContractInvalidSignature
106106
}
107+
case object ContractVSYSBalanceInsufficient extends ContractValidationError {
108+
override val transactionStatus = TransactionStatus.ContractVSYSBalanceInsufficient
109+
}
107110
case object EmptyProofs extends ValidationError
108111
case class InvalidSignature(s: Signed, details: Option[InvalidSignature] = None) extends ValidationError
109112
case class AccountBalanceError(errs: Map[Account, String]) extends ValidationError

src/test/scala/vsys/blockchain/state/contract/token/ExecuteTokenContractDiffTest.scala

+17-3
Original file line numberDiff line numberDiff line change
@@ -267,16 +267,17 @@ class ExecuteTokenContractDiffTest extends PropSpec
267267
}
268268
}
269269

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

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

296+
property("execute contract transaction systemSend failed dual to insufficient VSYS") {
297+
forAll(preconditionsAndExecuteContractSystemSend) { case (genesis, _, executeContractSystemSend2: ExecuteContractFunctionTransaction, fee: Long, recipient) =>
298+
assertDiffEi(Seq(TestBlock.create(Seq(genesis))), TestBlock.createWithTxStatus(Seq(executeContractSystemSend2), TransactionStatus.ContractVSYSBalanceInsufficient)) { blockDiffEi =>
299+
blockDiffEi shouldBe an[Right[_, _]]
300+
val totalPortfolioDiff: Portfolio = Monoid.combineAll(blockDiffEi.explicitGet().txsDiff.portfolios.values)
301+
totalPortfolioDiff.balance shouldBe -fee
302+
blockDiffEi.explicitGet().txsDiff.contractNumDB.isEmpty shouldBe true
303+
blockDiffEi.explicitGet().txsDiff.contractDB.isEmpty shouldBe true
304+
blockDiffEi.explicitGet().txsDiff.txStatus shouldBe TransactionStatus.ContractVSYSBalanceInsufficient
305+
}
306+
}
307+
}
308+
295309
}

src/test/scala/vsys/blockchain/state/diffs/CommonValidationContractTest.scala

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

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

0 commit comments

Comments
 (0)