From 2d7acf92a8901a7d01b9a4ddb7a7e8564dc572ae Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 18 Jan 2024 21:19:23 +0100 Subject: [PATCH 01/36] sigma-5.0.14: code migrated to the version of Sigma --- build.sbt | 2 +- .../org/ergoplatform/http/api/ApiCodecs.scala | 13 +++--- .../mining/AutolykosPowScheme.scala | 4 +- .../mining/AutolykosSolution.scala | 3 +- .../org/ergoplatform/mining/WorkMessage.scala | 2 +- .../org/ergoplatform/mining/mining.scala | 5 +-- .../modifiers/history/PreHeader.scala | 6 +-- .../modifiers/history/header/Header.scala | 7 +-- .../modifiers/mempool/ErgoTransaction.scala | 5 +-- .../nodeView/state/ErgoStateContext.scala | 10 ++--- .../org/ergoplatform/settings/Constants.scala | 7 ++- .../settings/ErgoValidationSettings.scala | 2 +- .../ErgoValidationSettingsUpdate.scala | 7 ++- .../settings/ValidationRules.scala | 2 +- .../org/ergoplatform/utils/BoxUtils.scala | 3 +- .../interface4j/crypto/ErgoSignature.java | 2 +- .../contracts/ReemissionContracts.scala | 9 ++-- .../wallet/boxes/BoxSelector.scala | 2 +- .../wallet/boxes/ErgoBoxSerializer.scala | 4 +- .../wallet/crypto/ErgoSignature.scala | 4 +- .../wallet/interpreter/ErgoInterpreter.scala | 4 +- .../interpreter/ErgoProvingInterpreter.scala | 11 ++--- .../wallet/interpreter/ErgoUnsafeProver.scala | 2 +- .../wallet/mnemonic/Mnemonic.scala | 2 +- .../protocol/context/InputContext.scala | 2 +- .../serialization/ErgoWalletSerializer.scala | 3 +- .../transactions/TransactionBuilder.scala | 3 +- .../wallet/boxes/DefaultBoxSelectorSpec.scala | 43 ++++++++++--------- ...ReplaceCompactCollectBoxSelectorSpec.scala | 8 ++-- .../ErgoProvingInterpreterSpec.scala | 13 +++--- .../interpreter/InterpreterSpecCommon.scala | 7 +-- .../transactions/TransactionBuilderSpec.scala | 17 ++++---- .../wallet/utils/Generators.scala | 19 ++++---- .../http/api/ApiRequestsCodecs.scala | 2 +- .../http/api/BlockchainApiRoute.scala | 2 +- .../http/api/ErgoBaseApiRoute.scala | 4 +- .../http/api/ErgoUtilsApiRoute.scala | 4 +- .../http/api/MiningApiRoute.scala | 2 +- .../ergoplatform/http/api/ScanApiRoute.scala | 4 +- .../http/api/ScriptApiRoute.scala | 13 +++--- .../http/api/TransactionsApiRoute.scala | 4 +- .../http/api/requests/CryptoResult.scala | 2 +- .../api/requests/HintExtractionRequest.scala | 2 +- .../mining/CandidateGenerator.scala | 15 +++---- .../mining/DefaultFakePowScheme.scala | 2 +- .../org/ergoplatform/mining/ErgoMiner.scala | 3 +- .../nodeView/history/extra/ExtraIndexer.scala | 2 +- .../history/extra/IndexedErgoAddress.scala | 2 +- .../nodeView/history/extra/IndexedToken.scala | 12 +++--- .../nodeView/state/ErgoState.scala | 12 +++--- .../wallet/ErgoWalletActorMessages.scala | 4 +- .../nodeView/wallet/ErgoWalletReader.scala | 2 +- .../nodeView/wallet/ErgoWalletService.scala | 4 +- .../nodeView/wallet/ErgoWalletSupport.scala | 8 ++-- .../nodeView/wallet/IdUtils.scala | 4 +- .../nodeView/wallet/WalletCache.scala | 6 +-- .../wallet/persistence/WalletStorage.scala | 2 +- .../wallet/requests/AssetIssueRequest.scala | 3 +- .../wallet/requests/PaymentRequest.scala | 3 +- .../wallet/scanning/ScanningPredicate.scala | 28 ++++++------ .../ScanningPredicateJsonCodecs.scala | 3 +- .../ScanningPredicateSerializer.scala | 5 +-- .../reemission/ReemissionRulesUtils.scala | 7 ++- .../ergoplatform/settings/ErgoSettings.scala | 2 +- .../http/routes/ScanApiRouteSpec.scala | 2 +- .../http/routes/ScriptApiRouteSpec.scala | 13 +++--- .../http/routes/TransactionApiRouteSpec.scala | 5 +-- .../http/routes/UtilsApiRouteSpec.scala | 3 +- .../local/MempoolAuditorSpec.scala | 8 ++-- .../mining/CandidateGeneratorPropSpec.scala | 2 +- .../mining/CandidateGeneratorSpec.scala | 7 +-- .../ergoplatform/mining/ErgoMinerSpec.scala | 32 +++++++------- .../mempool/ErgoTransactionSpec.scala | 19 ++++---- .../mempool/ExpirationSpecification.scala | 7 ++- .../HeaderSerializationSpecification.scala | 2 +- .../history/extra/ChainGenerator.scala | 9 ++-- .../nodeView/mempool/ErgoMemPoolSpec.scala | 12 +++--- .../nodeView/mempool/ScriptsSpec.scala | 42 ++++++++++-------- .../state/DigestStateSpecification.scala | 2 +- .../state/UtxoStateSpecification.scala | 11 ++--- .../wallet/ErgoWalletServiceSpec.scala | 9 ++-- .../nodeView/wallet/ErgoWalletSpec.scala | 17 ++++---- .../nodeView/wallet/WalletScanLogicSpec.scala | 24 +++++++---- .../persistence/OffChainRegistrySpec.scala | 2 +- .../persistence/WalletRegistryBenchmark.scala | 10 ++--- ...ningPredicateJsonCodecsSpecification.scala | 2 +- .../ScanningPredicateSpecification.scala | 6 +-- .../reemission/ReemissionRulesSpec.scala | 12 +++--- .../serialization/JsonSerializationSpec.scala | 3 +- .../settings/VotingSpecification.scala | 7 +-- .../ergoplatform/tools/ChainGenerator.scala | 2 +- .../org/ergoplatform/tools/FeeSimulator.scala | 8 ++-- .../utils/ErgoTestConstants.scala | 9 ++-- .../scala/org/ergoplatform/utils/Stubs.scala | 8 ++-- .../ergoplatform/utils/WalletTestOps.scala | 8 ++-- .../utils/generators/ChainGenerator.scala | 3 +- .../utils/generators/ErgoGenerators.scala | 17 ++++---- .../ErgoTransactionGenerators.scala | 10 ++--- .../utils/generators/WalletGenerators.scala | 2 +- 99 files changed, 371 insertions(+), 365 deletions(-) diff --git a/build.sbt b/build.sbt index c173d2fc1c..7b35d07c6f 100644 --- a/build.sbt +++ b/build.sbt @@ -37,7 +37,7 @@ val circeVersion = "0.13.0" val akkaVersion = "2.6.10" val akkaHttpVersion = "10.2.4" -val sigmaStateVersion = "5.0.13" +val sigmaStateVersion = "5.0.13-181-c2d4cc97-SNAPSHOT" val ficusVersion = "1.4.7" // for testing current sigmastate build (see sigmastate-ergo-it jenkins job) diff --git a/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala b/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala index 1b6c9b2214..e27d66153b 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala @@ -21,17 +21,16 @@ import scorex.crypto.authds.merkle.MerkleProof import scorex.crypto.authds.{LeafData, Side} import scorex.crypto.hash.Digest import scorex.util.encode.Base16 -import sigmastate.Values.SigmaBoolean import sigmastate._ -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.crypto.DLogProtocol.{DLogProverInput, FirstDLogProverMessage, ProveDlog} +import sigmastate.crypto.DLogProtocol.{DLogProverInput, FirstDLogProverMessage} import sigmastate.crypto.VerifierMessage.Challenge import sigmastate.crypto._ import sigmastate.interpreter._ -import sigmastate.serialization.OpCodes +import sigma.serialization.{OpCodes, SigSerializer} import org.ergoplatform.sdk.JsonCodecs -import sigmastate.eval.Extensions.ArrayOps -import sigmastate.utils.Helpers._ +import sigma.Extensions.ArrayOps +import sigma.crypto._ +import sigma.data._ import java.math.BigInteger import scala.annotation.nowarn @@ -129,7 +128,7 @@ trait ApiCodecs extends JsonCodecs { }) implicit val secretBigIntEncoder: Encoder[BigInteger] = Encoder.instance { w => - ErgoAlgos.encode(BigIntegers.asUnsignedByteArray(CryptoConstants.groupSize, w)).asJson + ErgoAlgos.encode(BigIntegers.asUnsignedByteArray(sigma.crypto.groupSize, w)).asJson } implicit val secretBigIntDecoder: Decoder[BigInteger] = arrayBytesDecoder.map { bytes => diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala index 5dd710da26..3b50158cc8 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala @@ -15,8 +15,8 @@ import org.ergoplatform.nodeView.mempool.TransactionMembershipProof import scorex.crypto.authds.{ADDigest, SerializedAdProof} import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.{ModifierId, ScorexLogging} -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.crypto.CryptoFacade +import sigma.crypto.CryptoFacade +import sigma.data.ProveDlog import scala.annotation.tailrec import scala.util.Try diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala index cf745e685b..20f3237a10 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala @@ -10,8 +10,7 @@ import org.ergoplatform.modifiers.history.header.Header.Version import org.ergoplatform.settings.Algos import org.ergoplatform.serialization.ErgoSerializer import scorex.util.serialization.{Reader, Writer} -import sigmastate.crypto.CryptoConstants -import sigmastate.crypto.CryptoConstants.EcPointType +import sigma.crypto.{CryptoConstants, EcPointType} /** * Solution for an Autolykos PoW puzzle. diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala index b79ffd1d08..5262bdc852 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala @@ -4,7 +4,7 @@ import io.circe.syntax._ import io.circe.{Encoder, Json} import org.ergoplatform.http.api.ApiCodecs import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Height -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.data.ProveDlog /** diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala index e469225906..fd3f59888f 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala @@ -2,10 +2,9 @@ package org.ergoplatform import org.bouncycastle.util.BigIntegers import scorex.crypto.hash.Blake2b256 -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.crypto.{BcDlogGroup, CryptoConstants} +import sigma.crypto.{BcDlogGroup, CryptoConstants, EcPointType} +import sigma.serialization.{GroupElementSerializer, SigmaSerializer} import sigmastate.crypto.DLogProtocol.DLogProverInput -import sigmastate.serialization.{GroupElementSerializer, SigmaSerializer} package object mining { diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala index 7710383183..946f42b3b0 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala @@ -6,9 +6,9 @@ import org.ergoplatform.modifiers.history.header.Header._ import org.ergoplatform.nodeView.history.ErgoHistoryUtils._ import org.ergoplatform.settings.Constants import scorex.util._ -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.eval.CGroupElement -import sigmastate.eval.Extensions._ +import sigma.Extensions.ArrayOps +import sigma.crypto.EcPointType +import sigma.data.CGroupElement /** * Only header fields that can be predicted by a miner diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala index 092dcd219f..98a4947bc5 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala @@ -17,9 +17,10 @@ import org.ergoplatform.serialization.ErgoSerializer import scorex.crypto.authds.ADDigest import scorex.crypto.hash.Digest32 import scorex.util._ -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.eval.Extensions._ -import sigmastate.eval.{CAvlTree, CBigInt, CGroupElement, CHeader} +import sigma.Extensions.ArrayOps +import sigma.crypto.EcPointType +import sigma.data.{CAvlTree, CBigInt, CGroupElement} +import sigmastate.eval.CHeader import scala.annotation.nowarn import scala.concurrent.duration.FiniteDuration diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala index ab5c064f53..b2b9f1f082 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala @@ -3,7 +3,7 @@ package org.ergoplatform.modifiers.mempool import io.circe.syntax._ import org.ergoplatform.{DataInput, ErgoBox, ErgoBoxCandidate, ErgoLikeTransaction, ErgoLikeTransactionSerializer, Input} import org.ergoplatform.ErgoBox.BoxId -import org.ergoplatform.SigmaConstants.{MaxBoxSize, MaxPropositionBytes} +import sigma.data.SigmaConstants.{MaxBoxSize, MaxPropositionBytes} import org.ergoplatform.http.api.ApiCodecs import org.ergoplatform.mining.emission.EmissionRules import org.ergoplatform.modifiers.history.header.Header @@ -27,8 +27,7 @@ import org.ergoplatform.validation.{InvalidModifier, ModifierValidator, Validati import scorex.db.ByteArrayUtils import scorex.util.serialization.{Reader, Writer} import scorex.util.{ModifierId, ScorexLogging, bytesToId} -import sigmastate.serialization.ConstantStore -import sigmastate.utils.{SigmaByteReader, SigmaByteWriter} +import sigma.serialization.{ConstantStore, SigmaByteReader, SigmaByteWriter} import java.util import scala.annotation.nowarn diff --git a/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala index d4ac70befb..23311a896f 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala @@ -18,10 +18,10 @@ import org.ergoplatform.validation.{InvalidModifier, ModifierValidator, Validati import scorex.crypto.authds.ADDigest import scorex.util.ScorexLogging import scorex.util.serialization.{Reader, Writer} -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.eval.Extensions.ArrayOps -import sigmastate.eval.SigmaDsl -import sigma.Coll +import sigma.Extensions.ArrayOps +import sigma.crypto.EcPointType +import sigma.{Coll, Colls} +import sigma.eval.SigmaDsl import scala.collection.compat.immutable.ArraySeq import scala.util.{Failure, Success, Try} @@ -82,7 +82,7 @@ class ErgoStateContext(val lastHeaders: Seq[Header], PreHeader.toSigma(lastHeaders.headOption.getOrElse(PreHeader.fake)) override def sigmaLastHeaders: Coll[sigma.Header] = - SigmaDsl.Colls.fromArray(lastHeaders.drop(1).map(h => Header.toSigma(h)).toArray) + Colls.fromArray(lastHeaders.drop(1).map(h => Header.toSigma(h)).toArray) // todo remove from ErgoLikeContext and from ErgoStateContext // State root hash before the last block diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/Constants.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/Constants.scala index 02090c6afd..fabdb3e11a 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/Constants.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/Constants.scala @@ -3,8 +3,7 @@ package org.ergoplatform.settings import org.ergoplatform.mining.difficulty.DifficultySerializer import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Difficulty import scorex.crypto.authds.avltree.batch.AvlTreeParameters -import sigmastate.Values -import sigmastate.Values.ErgoTree +import sigma.ast.ErgoTree object Constants { /** @@ -42,8 +41,8 @@ object Constants { val SoftForkEpochs = 32 //about 45.5 days - def TrueLeaf: ErgoTree = Values.TrueLeaf.toSigmaProp - def FalseLeaf: ErgoTree = Values.FalseLeaf.toSigmaProp + def TrueLeaf: ErgoTree = ErgoTree.fromProposition(sigma.ast.TrueLeaf.toSigmaProp) + def FalseLeaf: ErgoTree = ErgoTree.fromProposition(sigma.ast.FalseLeaf.toSigmaProp) val StringEncoding = "UTF-8" diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala index 3961e5f159..c102a4b52f 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala @@ -4,10 +4,10 @@ import org.ergoplatform.core.BytesSerializable import org.ergoplatform.http.api.ApiCodecs import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate} import org.ergoplatform.utils -import org.ergoplatform.validation.SigmaValidationSettings import org.ergoplatform.serialization.ErgoSerializer import org.ergoplatform.validation.{InvalidModifier, ModifierValidator, ValidationResult, ValidationSettings} import scorex.util.serialization.{Reader, Writer} +import sigma.validation.SigmaValidationSettings import scala.util.Try diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala index a98066a696..74d7062fe2 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala @@ -3,11 +3,10 @@ package org.ergoplatform.settings import org.ergoplatform.validation.RuleStatusSerializer import org.ergoplatform.serialization.ErgoSerializer import scorex.util.serialization.{Reader, Writer} -import sigmastate.serialization.ConstantStore -import sigmastate.utils.{SigmaByteReader, SigmaByteWriter} +import sigma.serialization.{ConstantStore, SigmaByteReader, SigmaByteWriter} case class ErgoValidationSettingsUpdate(rulesToDisable: Seq[Short], - statusUpdates: Seq[(Short, org.ergoplatform.validation.RuleStatus)]) { + statusUpdates: Seq[(Short, sigma.validation.RuleStatus)]) { def ++(that: ErgoValidationSettingsUpdate): ErgoValidationSettingsUpdate = { val newRules = (rulesToDisable ++ that.rulesToDisable).distinct.sorted @@ -23,7 +22,7 @@ object ErgoValidationSettingsUpdate { object ErgoValidationSettingsUpdateSerializer extends ErgoSerializer[ErgoValidationSettingsUpdate] { - private val FirstRule = org.ergoplatform.validation.ValidationRules.FirstRuleId + private val FirstRule = sigma.validation.ValidationRules.FirstRuleId override def serialize(obj: ErgoValidationSettingsUpdate, w: Writer): Unit = { val sigmaWriter = new SigmaByteWriter(w, None) diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/ValidationRules.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ValidationRules.scala index 96029c0994..b33234f2d2 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/ValidationRules.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ValidationRules.scala @@ -1,6 +1,6 @@ package org.ergoplatform.settings -import org.ergoplatform.SigmaConstants.{MaxBoxSize, MaxPropositionBytes} +import sigma.data.SigmaConstants.{MaxBoxSize, MaxPropositionBytes} import org.ergoplatform.modifiers.{ErgoFullBlock, NetworkObjectTypeId} import org.ergoplatform.modifiers.history.extension.Extension import org.ergoplatform.modifiers.history.header.Header diff --git a/ergo-core/src/main/scala/org/ergoplatform/utils/BoxUtils.scala b/ergo-core/src/main/scala/org/ergoplatform/utils/BoxUtils.scala index 3802b08077..5af2fd8bb4 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/utils/BoxUtils.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/utils/BoxUtils.scala @@ -5,8 +5,7 @@ import org.ergoplatform.settings.{Algos, Parameters} import org.ergoplatform.{ErgoBox, ErgoBoxCandidate} import scorex.util.ModifierId import sigma.{Coll, Colls} -import sigmastate.Values.ErgoTree -import sigmastate.eval._ +import sigma.ast.ErgoTree object BoxUtils { diff --git a/ergo-wallet/src/main/java/org/ergoplatform/wallet/interface4j/crypto/ErgoSignature.java b/ergo-wallet/src/main/java/org/ergoplatform/wallet/interface4j/crypto/ErgoSignature.java index 989363a6f2..5bcfabbe3a 100644 --- a/ergo-wallet/src/main/java/org/ergoplatform/wallet/interface4j/crypto/ErgoSignature.java +++ b/ergo-wallet/src/main/java/org/ergoplatform/wallet/interface4j/crypto/ErgoSignature.java @@ -2,7 +2,7 @@ import org.bouncycastle.math.ec.custom.sec.SecP256K1Point; import scala.math.BigInt; -import sigmastate.crypto.Platform; +import sigma.crypto.Platform; import java.math.BigInteger; diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/contracts/ReemissionContracts.scala b/ergo-wallet/src/main/scala/org/ergoplatform/contracts/ReemissionContracts.scala index 7569b8c00c..4dd66c3d9d 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/contracts/ReemissionContracts.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/contracts/ReemissionContracts.scala @@ -4,11 +4,10 @@ import org.ergoplatform.ErgoBox.{R2, STokensRegType} import org.ergoplatform.ErgoTreePredef.{boxCreationHeight, expectedMinerOutScriptBytesVal} import org.ergoplatform.mining.emission.EmissionRules.CoinsInOneErgo import org.ergoplatform.settings.MonetarySettings -import org.ergoplatform.{Height, MinerPubkey, Outputs, Self} -import sigmastate.Values.{ByteArrayConstant, ErgoTree, IntConstant, LongConstant, SigmaPropValue, Value} -import sigmastate.utxo._ import sigmastate._ import sigma.Coll +import sigma.ast._ +import sigma.ast.syntax._ /** * Container for re-emission related contracts. Contains re-emission contract and pay-to-reemission contract. @@ -39,7 +38,9 @@ trait ReemissionContracts { /** Helper method to produce v1 tree from a SigmaPropValue instance (i.e. root node of AST).*/ private def v1Tree(prop: SigmaPropValue): ErgoTree = { val version: Byte = 1 - val headerFlags = ErgoTree.headerWithVersion(version) + // it used to be ErgoTree.headerWithVersion(version) before Sigma v5.0.14, + // which used the default header, now this is made explicit via naming + val headerFlags = ErgoTree.defaultHeaderWithVersion(version) ErgoTree.fromProposition(headerFlags, prop) } diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/boxes/BoxSelector.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/boxes/BoxSelector.scala index f945b3e4bf..8f98714aed 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/boxes/BoxSelector.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/boxes/BoxSelector.scala @@ -1,10 +1,10 @@ package org.ergoplatform.wallet.boxes -import org.ergoplatform.SigmaConstants.MaxBoxSize import org.ergoplatform.sdk.wallet.TokensMap import org.ergoplatform.wallet.boxes.BoxSelector.{BoxSelectionError, BoxSelectionResult} import org.ergoplatform.{ErgoBoxAssets, ErgoBoxAssetsHolder} import scorex.util.ScorexLogging +import sigma.data.SigmaConstants.MaxBoxSize /** diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/boxes/ErgoBoxSerializer.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/boxes/ErgoBoxSerializer.scala index 6c5fb62563..7bd3bb4c59 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/boxes/ErgoBoxSerializer.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/boxes/ErgoBoxSerializer.scala @@ -3,8 +3,8 @@ package org.ergoplatform.wallet.boxes import org.ergoplatform.ErgoBox import org.ergoplatform.wallet.serialization.ErgoWalletSerializer import scorex.util.serialization.{Reader, Writer} -import sigmastate.serialization.ConstantStore -import sigmastate.utils.{SigmaByteReader, SigmaByteWriter} +import sigma.serialization.ConstantStore +import sigma.serialization.{SigmaByteReader, SigmaByteWriter} object ErgoBoxSerializer extends ErgoWalletSerializer[ErgoBox] { diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/crypto/ErgoSignature.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/crypto/ErgoSignature.scala index 430fc8c894..9b1b7c00cd 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/crypto/ErgoSignature.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/crypto/ErgoSignature.scala @@ -3,8 +3,8 @@ package org.ergoplatform.wallet.crypto import org.bouncycastle.util.BigIntegers import scorex.crypto.hash.Blake2b256 import scorex.util.encode.Base16 -import sigmastate.crypto.CryptoConstants -import sigmastate.serialization.GroupElementSerializer +import sigma.crypto.{CryptoConstants, EcPointType} +import sigma.serialization.GroupElementSerializer import scala.annotation.tailrec diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoInterpreter.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoInterpreter.scala index bdd423615f..072fa40f38 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoInterpreter.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoInterpreter.scala @@ -5,9 +5,9 @@ import org.ergoplatform.sdk.BlockchainParameters import org.ergoplatform.wallet.protocol.Constants import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoLikeContext, ErgoLikeInterpreter} import scorex.util.ScorexLogging -import sigmastate.Values.ErgoTree +import sigma.ast.ErgoTree import sigmastate.interpreter.Interpreter.{ScriptEnv, VerificationResult} -import sigmastate.{AvlTreeData, AvlTreeFlags} +import sigma.data.{AvlTreeData, AvlTreeFlags} import sigma.Coll import scala.util.Try diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoProvingInterpreter.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoProvingInterpreter.scala index 62732ab788..3cf842b6ec 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoProvingInterpreter.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoProvingInterpreter.scala @@ -5,13 +5,14 @@ import org.ergoplatform.sdk.BlockchainParameters import org.ergoplatform.sdk.utils.ArithUtils.{addExact, multiplyExact} import org.ergoplatform.sdk.wallet.protocol.context.BlockchainStateContext import org.ergoplatform.sdk.wallet.secrets.{ExtendedPublicKey, ExtendedSecretKey, SecretKey} -import org.ergoplatform.validation.{SigmaValidationSettings, ValidationRules} +import org.ergoplatform.validation.ValidationRules import org.ergoplatform.wallet.boxes.ErgoBoxAssetExtractor import scorex.util.encode.Base16 -import sigmastate.AvlTreeData -import sigmastate.Values.SigmaBoolean +import sigma.interpreter.ContextExtension +import sigma.validation.SigmaValidationSettings +import sigma.data.{AvlTreeData, SigmaBoolean, SigmaLeaf} import sigmastate.crypto.SigmaProtocolPrivateInput -import sigmastate.interpreter.{ContextExtension, ProverInterpreter} +import sigmastate.interpreter.ProverInterpreter import sigma.{Coll, Header, PreHeader} import java.util @@ -45,7 +46,7 @@ class ErgoProvingInterpreter(val secretKeys: IndexedSeq[SecretKey], /** * Interpreter's secrets, in form of sigma protocols private inputs */ - val secrets: IndexedSeq[SigmaProtocolPrivateInput[_]] = secretKeys.map(_.privateInput) + val secrets: IndexedSeq[SigmaProtocolPrivateInput[_]] = secretKeys.map(_.privateInput.asInstanceOf[SigmaProtocolPrivateInput[_ <: SigmaLeaf]]) /** * Only secrets corresponding to hierarchical deterministic scheme (BIP-32 impl) diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoUnsafeProver.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoUnsafeProver.scala index c2b763cb65..6dbe2542dc 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoUnsafeProver.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/interpreter/ErgoUnsafeProver.scala @@ -3,7 +3,7 @@ package org.ergoplatform.wallet.interpreter import org.ergoplatform.{ErgoLikeTransaction, Input, UnsignedErgoLikeTransaction} import scorex.util.encode.Base16 import sigmastate.crypto.DLogProtocol.DLogProverInput -import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigma.interpreter.{ContextExtension, ProverResult} /** * A naive Ergo prover implementation not performing transaction cost verification. diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/mnemonic/Mnemonic.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/mnemonic/Mnemonic.scala index 46871b6bdb..5916eb2a02 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/mnemonic/Mnemonic.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/mnemonic/Mnemonic.scala @@ -6,7 +6,7 @@ import javax.crypto.SecretKeyFactory import javax.crypto.spec.PBEKeySpec import org.ergoplatform.wallet.interface4j.SecretString import scodec.bits.BitVector -import sigmastate.crypto.CryptoFacade +import sigma.crypto.CryptoFacade import scala.util.{Failure, Try} diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/protocol/context/InputContext.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/protocol/context/InputContext.scala index 941ab34052..1ed6f117ca 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/protocol/context/InputContext.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/protocol/context/InputContext.scala @@ -1,6 +1,6 @@ package org.ergoplatform.wallet.protocol.context -import sigmastate.interpreter.ContextExtension +import sigma.interpreter.ContextExtension /** * Part of execution context regarding a box to be spent. diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/serialization/ErgoWalletSerializer.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/serialization/ErgoWalletSerializer.scala index bc9bf9071b..4f69d11421 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/serialization/ErgoWalletSerializer.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/serialization/ErgoWalletSerializer.scala @@ -3,8 +3,7 @@ package org.ergoplatform.wallet.serialization import java.nio.ByteBuffer import scorex.util.ByteArrayBuilder import scorex.util.serialization._ -import sigmastate.serialization.{SigmaSerializer, ConstantStore} -import sigmastate.utils.{SigmaByteWriter, SigmaByteReader} +import sigma.serialization._ import scala.util.Try diff --git a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/transactions/TransactionBuilder.scala b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/transactions/TransactionBuilder.scala index 745002eacf..e09185060b 100644 --- a/ergo-wallet/src/main/scala/org/ergoplatform/wallet/transactions/TransactionBuilder.scala +++ b/ergo-wallet/src/main/scala/org/ergoplatform/wallet/transactions/TransactionBuilder.scala @@ -7,8 +7,7 @@ import org.ergoplatform.wallet.boxes.{BoxSelector, DefaultBoxSelector} import scorex.crypto.authds.ADKey import scorex.util.encode.Base16 import scorex.util.{ModifierId, bytesToId} -import sigmastate.eval.Extensions._ -import sigmastate.eval._ +import sigma.eval.Extensions.EvalIterableOps import sigmastate.utils.Extensions._ import sigma.Coll import sigma.Extensions._ diff --git a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/boxes/DefaultBoxSelectorSpec.scala b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/boxes/DefaultBoxSelectorSpec.scala index f34f050501..ec15eb83b7 100644 --- a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/boxes/DefaultBoxSelectorSpec.scala +++ b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/boxes/DefaultBoxSelectorSpec.scala @@ -2,7 +2,6 @@ package org.ergoplatform.wallet.boxes import org.ergoplatform.ErgoBox.TokenId import org.ergoplatform.ErgoLikeTransaction -import org.ergoplatform.SigmaConstants.MaxBoxSize import org.ergoplatform.sdk.wallet.Constants.MaxAssetsPerBox import org.ergoplatform.wallet.Constants.PaymentsScanId import org.ergoplatform.wallet.boxes.DefaultBoxSelector.{NotEnoughErgsError, NotEnoughTokensError} @@ -11,12 +10,13 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import scorex.crypto.hash.Blake2b256 import scorex.util.bytesToId -import sigmastate.Values -import sigmastate.Values.SigmaPropValue import sigmastate.eval.Extensions._ import sigmastate.helpers.TestingHelpers._ import sigmastate.utils.Extensions._ import sigma.Extensions._ +import sigma.ast.ErgoTree +import sigma.ast.syntax.SigmaPropValue +import sigma.data.SigmaConstants.MaxBoxSize import scala.util.Random @@ -27,7 +27,8 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues private val onChainFilter = {box: TrackedBox => box.chainStatus.onChain} private val parentTx = ErgoLikeTransaction(IndexedSeq(), IndexedSeq()) - private val TrueLeaf: SigmaPropValue = Values.TrueLeaf.toSigmaProp + private val TrueLeaf: SigmaPropValue = sigma.ast.TrueLeaf.toSigmaProp + private val TrueTree = ErgoTree.fromProposition(TrueLeaf) private val StartHeight: Int = 0 private def genTokens(count: Int) = { @@ -37,7 +38,7 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues private val selector = new DefaultBoxSelector(None) property("returns error when it is impossible to select coins") { - val box = testBox(1, TrueLeaf, creationHeight = StartHeight) + val box = testBox(1, TrueTree, creationHeight = StartHeight) val uBox = TrackedBox(parentTx, 0, None, box, Set(PaymentsScanId)) //target amount is too high @@ -55,9 +56,9 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues } property("properly selects coins - simple case with no assets") { - val box1 = testBox(1, TrueLeaf, creationHeight = StartHeight) - val box2 = testBox(10, TrueLeaf, creationHeight = StartHeight) - val box3 = testBox(100, TrueLeaf, creationHeight = StartHeight) + val box1 = testBox(1, TrueTree, creationHeight = StartHeight) + val box2 = testBox(10, TrueTree, creationHeight = StartHeight) + val box3 = testBox(100, TrueTree, creationHeight = StartHeight) val uBox1 = TrackedBox(parentTx, 0, Option(100), box1, Set(PaymentsScanId)) val uBox2 = TrackedBox(parentTx, 1, None, box2, Set(PaymentsScanId)) @@ -101,9 +102,9 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues val assetId2 = bytesToId(Blake2b256("world")) val parentTx = ErgoLikeTransaction(IndexedSeq(), IndexedSeq()) - val box1 = testBox(1 * MinBoxValue, TrueLeaf, StartHeight, Seq(assetId1.toTokenId -> 1)) - val box2 = testBox(10 * MinBoxValue, TrueLeaf, StartHeight, Seq(assetId2.toTokenId -> 10)) - val box3 = testBox(100 * MinBoxValue, TrueLeaf, StartHeight, Seq(assetId1.toTokenId -> 100)) + val box1 = testBox(1 * MinBoxValue, TrueTree, StartHeight, Seq(assetId1.toTokenId -> 1)) + val box2 = testBox(10 * MinBoxValue, TrueTree, StartHeight, Seq(assetId2.toTokenId -> 10)) + val box3 = testBox(100 * MinBoxValue, TrueTree, StartHeight, Seq(assetId1.toTokenId -> 100)) val uBox1 = TrackedBox(parentTx, 0, Some(100), box1, Set(PaymentsScanId)) val uBox2 = TrackedBox(parentTx, 1, None, box2, Set(PaymentsScanId)) @@ -150,17 +151,17 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues val assetId8 = bytesToId(Blake2b256("8")) val box1 = testBox( - 1 * MinBoxValue, TrueLeaf, StartHeight, + 1 * MinBoxValue, TrueTree, StartHeight, Seq(assetId1.toTokenId -> 1, assetId2.toTokenId -> 1, assetId3.toTokenId -> 1, assetId4.toTokenId -> 1)) val box2 = testBox( - 10 * MinBoxValue, TrueLeaf, StartHeight, + 10 * MinBoxValue, TrueTree, StartHeight, Seq(assetId5.toTokenId -> 10, assetId6.toTokenId -> 10, assetId7.toTokenId -> 10, assetId8.toTokenId -> 10)) val box3 = testBox( - 100 * MinBoxValue, TrueLeaf, StartHeight, + 100 * MinBoxValue, TrueTree, StartHeight, Seq(assetId3.toTokenId -> 100, assetId4.toTokenId -> 100, assetId5.toTokenId -> 100, assetId6.toTokenId -> 100)) @@ -201,13 +202,13 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues val tokens = (0 until MaxAssetsPerBox).map { _ => (scorex.util.Random.randomBytes(TokenId.size).toTokenId, Random.nextInt(100000000).toLong) } - val box = testBox(1 * MinBoxValue, TrueLeaf, StartHeight, tokens) + val box = testBox(1 * MinBoxValue, TrueTree, StartHeight, tokens) assert(box.bytes.length <= MaxBoxSize.value) } property("Select boxes such that change boxes are grouped by MaxAssetsPerBox") { // make selection such that '2 * MaxAssetsPerBox + 1' tokens generates exactly 2 change boxes with MaxAssetsPerBox tokens - val box1 = testBox(4 * MinBoxValue, TrueLeaf, StartHeight, genTokens(2 * MaxAssetsPerBox + 1)) + val box1 = testBox(4 * MinBoxValue, TrueTree, StartHeight, genTokens(2 * MaxAssetsPerBox + 1)) val uBox1 = TrackedBox(parentTx, 0, Some(100), box1, Set(PaymentsScanId)) val s1 = selector.select(Iterator(uBox1), noFilter, 1 * MinBoxValue, Map(bytesToId(Blake2b256("1")) -> 1)) s1 shouldBe 'right @@ -215,7 +216,7 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues s1.right.get.changeBoxes.forall(_.tokens.size == MaxAssetsPerBox) shouldBe true // make selection such that '2 * MaxAssetsPerBox + 2' tokens generates 3 change boxes, one with just a single token - val box2 = testBox(4 * MinBoxValue, TrueLeaf, StartHeight, genTokens(2 * MaxAssetsPerBox + 2)) + val box2 = testBox(4 * MinBoxValue, TrueTree, StartHeight, genTokens(2 * MaxAssetsPerBox + 2)) val uBox2 = TrackedBox(parentTx, 0, Some(100), box2, Set(PaymentsScanId)) val s2 = selector.select(Iterator(uBox2), noFilter, 1 * MinBoxValue, Map(bytesToId(Blake2b256("1")) -> 1)) s2 shouldBe 'right @@ -232,9 +233,9 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues val ergValue = 10 * MinBoxValue - val box1 = testBox(ergValue, TrueLeaf, StartHeight, Seq(tokenData)) + val box1 = testBox(ergValue, TrueTree, StartHeight, Seq(tokenData)) val uBox1 = TrackedBox(parentTx, 0, Some(100), box1, Set(PaymentsScanId)) - val box2 = testBox(ergValue, TrueLeaf, StartHeight) + val box2 = testBox(ergValue, TrueTree, StartHeight) val uBox2 = TrackedBox(parentTx, 0, Some(100), box2, Set(PaymentsScanId)) val s1 = selector.select(Iterator(uBox1, uBox2), noFilter, ergValue, Map.empty) @@ -242,7 +243,7 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues s1.right.get.changeBoxes.size shouldBe 1 s1.right.get.changeBoxes.head.tokens(tokenId) shouldBe 2 - val box3 = testBox(ergValue, TrueLeaf, StartHeight) + val box3 = testBox(ergValue, TrueTree, StartHeight) val uBox3 = TrackedBox(parentTx, 0, Some(100), box3, Set(PaymentsScanId)) val s2 = selector.select(Iterator(uBox2, uBox3), noFilter, ergValue, Map.empty) @@ -266,7 +267,7 @@ class DefaultBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues val fullValue = 2000000000L val reemissionAmt = fullValue / 2 - val inputBox = testBox(fullValue, TrueLeaf, StartHeight, Array((reemissionTokenId, reemissionAmt))) + val inputBox = testBox(fullValue, TrueTree, StartHeight, Array((reemissionTokenId, reemissionAmt))) val uBox = TrackedBox(parentTx, 0, Some(100), inputBox, Set(PaymentsScanId)) val s1 = selector.select(Iterator(uBox), noFilter, fullValue - reemissionAmt + 1, Map.empty) diff --git a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/boxes/ReplaceCompactCollectBoxSelectorSpec.scala b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/boxes/ReplaceCompactCollectBoxSelectorSpec.scala index 300905a6f1..00e3101d29 100644 --- a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/boxes/ReplaceCompactCollectBoxSelectorSpec.scala +++ b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/boxes/ReplaceCompactCollectBoxSelectorSpec.scala @@ -3,21 +3,21 @@ package org.ergoplatform.wallet.boxes import org.ergoplatform.wallet.Constants.PaymentsScanId import org.ergoplatform.ErgoLikeTransaction import org.ergoplatform.wallet.boxes.BoxSelector.BoxSelectionResult -import sigmastate.Values -import sigmastate.Values.SigmaPropValue import sigmastate.helpers.TestingHelpers._ import org.scalatest.EitherValues import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec +import sigma.ast.ErgoTree +import sigma.ast.syntax.SigmaPropValue class ReplaceCompactCollectBoxSelectorSpec extends AnyPropSpec with Matchers with EitherValues { private val noFilter: TrackedBox => Boolean = _ => true val parentTx = ErgoLikeTransaction(IndexedSeq(), IndexedSeq()) - val TrueLeaf: SigmaPropValue = Values.TrueLeaf.toSigmaProp + val TrueLeaf: SigmaPropValue = sigma.ast.TrueLeaf.toSigmaProp - def box(value:Long) = testBox(value, TrueLeaf, 0) + def box(value:Long) = testBox(value, ErgoTree.fromProposition(TrueLeaf), 0) def trackedBox(value:Long) = TrackedBox(parentTx, 0, None, box(value), Set(PaymentsScanId)) property("compress() done properly") { diff --git a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/interpreter/ErgoProvingInterpreterSpec.scala b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/interpreter/ErgoProvingInterpreterSpec.scala index e821987d01..1533537446 100644 --- a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/interpreter/ErgoProvingInterpreterSpec.scala +++ b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/interpreter/ErgoProvingInterpreterSpec.scala @@ -10,10 +10,11 @@ import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import scorex.util.{ModifierId, Random} import scorex.util.encode.Base16 import sigma.Colls -import sigmastate.CTHRESHOLD -import sigmastate.Values.{GroupElementConstant, SigmaBoolean} -import sigmastate.interpreter.{ContextExtension, HintsBag} -import sigmastate.serialization.ErgoTreeSerializer +import sigma.ast.{ErgoTree, GroupElementConstant} +import sigma.data.{CGroupElement, CTHRESHOLD, SigmaBoolean} +import sigma.interpreter.ContextExtension +import sigma.serialization.ErgoTreeSerializer +import sigmastate.interpreter.HintsBag class ErgoProvingInterpreterSpec @@ -63,7 +64,7 @@ class ErgoProvingInterpreterSpec val creationHeight = 10000 - val boxCandidate = new ErgoBoxCandidate(value, prop, creationHeight) + val boxCandidate = new ErgoBoxCandidate(value, ErgoTree.fromSigmaBoolean(prop), creationHeight) val fakeTxId = ModifierId @@ Base16.encode(Array.fill(32)(5: Byte)) val inputBox = boxCandidate.toBox(fakeTxId, 0.toShort) @@ -94,7 +95,7 @@ class ErgoProvingInterpreterSpec val value = 100000000L val creationHeight = 10000 - val boxCandidate = new ErgoBoxCandidate(value, pk, creationHeight) + val boxCandidate = new ErgoBoxCandidate(value, ErgoTree.fromSigmaBoolean(pk), creationHeight) val numOfInputs = 50 val fakeTxId = ModifierId @@ Base16.encode(Array.fill(32)(5: Byte)) diff --git a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/interpreter/InterpreterSpecCommon.scala b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/interpreter/InterpreterSpecCommon.scala index 5f797a27d2..127b20ff6e 100644 --- a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/interpreter/InterpreterSpecCommon.scala +++ b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/interpreter/InterpreterSpecCommon.scala @@ -3,9 +3,10 @@ package org.ergoplatform.wallet.interpreter import org.ergoplatform.sdk.BlockchainParameters import org.ergoplatform.sdk.wallet.protocol.context.BlockchainStateContext import scorex.util.encode.Base16 -import sigmastate.crypto.CryptoConstants -import sigmastate.eval.Extensions.ArrayOps -import sigmastate.eval.{CGroupElement, CPreHeader} +import sigma.Extensions.ArrayOps +import sigma.crypto.CryptoConstants +import sigma.data.CGroupElement +import sigmastate.eval.CPreHeader import sigma.{Coll, Colls, Header, PreHeader} trait InterpreterSpecCommon { diff --git a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/transactions/TransactionBuilderSpec.scala b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/transactions/TransactionBuilderSpec.scala index f3bb1b4cbc..213fb00086 100644 --- a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/transactions/TransactionBuilderSpec.scala +++ b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/transactions/TransactionBuilderSpec.scala @@ -9,13 +9,13 @@ import org.ergoplatform.wallet.interface4j.SecretString import org.ergoplatform.wallet.mnemonic.Mnemonic import org.ergoplatform.wallet.utils.WalletTestHelpers import org.scalatest.matchers.should.Matchers -import sigmastate.Values -import sigmastate.Values.SigmaPropValue +import sigma.ast.{ErgoTree, TrueLeaf} +import sigma.ast.syntax.SigmaPropValue import sigmastate.eval.Extensions._ -import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigmastate.utils.Extensions._ import sigmastate.utils.Helpers._ +import sigma.eval.Extensions.EvalIterableOps import scala.util.{Success, Try} @@ -35,20 +35,21 @@ class TransactionBuilderSpec extends WalletTestHelpers with Matchers { val minChangeValue = BoxSelector.MinBoxValue val minerRewardDelay = 720 - val TrueProp: SigmaPropValue = Values.TrueLeaf.toSigmaProp + val TrueProp: SigmaPropValue = TrueLeaf.toSigmaProp + val TrueTree = ErgoTree.fromProposition(TrueProp) val tid1 = stringToId("t1") val tid2 = stringToId("t2") - def box(value: Long) = testBox(value, TrueProp, currentHeight) + def box(value: Long) = testBox(value, TrueTree, currentHeight) def box(value: Long, tokens: Seq[(TokenId, Long)]) = - testBox(value, TrueProp, currentHeight, tokens) + testBox(value, TrueTree, currentHeight, tokens) - def boxCandidate(value: Long) = new ErgoBoxCandidate(value, TrueProp, currentHeight) + def boxCandidate(value: Long) = new ErgoBoxCandidate(value, TrueTree, currentHeight) def boxCandidate(value: Long, tokens: Seq[(TokenId, Long)]) = - new ErgoBoxCandidate(value, TrueProp, currentHeight, tokens.toColl) + new ErgoBoxCandidate(value, TrueTree, currentHeight, tokens.toColl) def transaction(inputBox: ErgoBox, outBox: ErgoBoxCandidate, diff --git a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/utils/Generators.scala b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/utils/Generators.scala index 8ba31c3c27..08902ed023 100644 --- a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/utils/Generators.scala +++ b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/utils/Generators.scala @@ -12,14 +12,14 @@ import org.scalacheck.Arbitrary.arbByte import org.scalacheck.{Arbitrary, Gen} import scorex.crypto.authds.ADKey import scorex.util._ -import sigmastate.Values.{ByteArrayConstant, CollectionConstant, ErgoTree, EvaluatedValue, FalseLeaf, TrueLeaf} -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.crypto.CryptoFacade.SecretKeyLength +import sigma.ast._ +import sigma.ast.syntax._ +import sigma.crypto.CryptoFacade.SecretKeyLength +import sigma.data.ProveDlog +import sigma.util.Extensions.SigmaBooleanOps import sigmastate.eval.Extensions._ -import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ -import sigmastate.{SByte, SType} - +import sigma.eval.Extensions.EvalIterableOps trait Generators { @@ -107,7 +107,7 @@ trait Generators { Gen.choose(minValue, CoinsTotalTest / 1000) } - def ergoBoxGen(propGen: Gen[ErgoTree] = Gen.const(TrueLeaf.toSigmaProp), + def ergoBoxGen(propGen: Gen[ErgoTree] = Gen.const(ErgoTree.fromProposition(TrueLeaf.toSigmaProp)), tokensGen: Gen[Seq[(TokenId, Long)]] = additionalTokensGen, valueGenOpt: Option[Gen[Long]] = None, heightGen: Gen[Int] = heightGen): Gen[ErgoBox] = for { @@ -174,7 +174,10 @@ trait Generators { def unsignedTxGen(secret: SecretKey): Gen[(IndexedSeq[ErgoBox], UnsignedErgoLikeTransaction)] = { - val dlog: Gen[ErgoTree] = Gen.const(secret.privateInput.publicImage.asInstanceOf[ProveDlog].toSigmaProp) + val dlog: Gen[ErgoTree] = Gen.const( + ErgoTree.fromProposition( + + secret.privateInput.publicImage.asInstanceOf[ProveDlog].toSigmaProp)) for { ins <- Gen.listOfN(2, ergoBoxGen(dlog)) diff --git a/src/main/scala/org/ergoplatform/http/api/ApiRequestsCodecs.scala b/src/main/scala/org/ergoplatform/http/api/ApiRequestsCodecs.scala index 916a660eea..ec7a0ebc10 100644 --- a/src/main/scala/org/ergoplatform/http/api/ApiRequestsCodecs.scala +++ b/src/main/scala/org/ergoplatform/http/api/ApiRequestsCodecs.scala @@ -9,7 +9,7 @@ import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, GenerateCommit import org.ergoplatform.sdk.wallet.secrets.{DhtSecretKey, DlogSecretKey} import org.ergoplatform.wallet.interpreter.TransactionHintsBag import sigma.AnyValue -import sigmastate.Values.SigmaBoolean +import sigma.data.SigmaBoolean /** * JSON codecs for HTTP API requests related entities diff --git a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala index 0be225d035..53db5fa8ea 100644 --- a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala @@ -20,7 +20,7 @@ import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings} import org.ergoplatform.http.api.ApiError.{BadRequest, InternalError} import scorex.core.api.http.ApiResponse import scorex.util.{ModifierId, bytesToId} -import sigmastate.Values.ErgoTree +import sigma.ast.ErgoTree import spire.implicits.cfor import scala.concurrent.duration.{Duration, SECONDS} diff --git a/src/main/scala/org/ergoplatform/http/api/ErgoBaseApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ErgoBaseApiRoute.scala index f12badfb0b..50162b59f9 100644 --- a/src/main/scala/org/ergoplatform/http/api/ErgoBaseApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/ErgoBaseApiRoute.scala @@ -16,8 +16,8 @@ import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGe import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.ProcessingOutcome import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.ProcessingOutcome._ import scorex.util.encode.Base16 -import sigmastate.Values.ErgoTree -import sigmastate.serialization.ErgoTreeSerializer +import sigma.ast.ErgoTree +import sigma.serialization.ErgoTreeSerializer import scala.concurrent.{ExecutionContextExecutor, Future} import scala.util.{Failure, Success, Try} diff --git a/src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala index 87775dba7a..f2d65ca128 100644 --- a/src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala @@ -12,11 +12,11 @@ import scorex.core.api.http.{ApiResponse, ApiRoute} import org.ergoplatform.utils.ScorexEncoding import scorex.crypto.hash.Blake2b256 import scorex.util.encode.Base16 -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.data.ProveDlog import java.security.SecureRandom import scala.util.Failure -import sigmastate.serialization.{ErgoTreeSerializer, GroupElementSerializer, SigmaSerializer} +import sigma.serialization.{ErgoTreeSerializer, GroupElementSerializer, SigmaSerializer} class ErgoUtilsApiRoute(val ergoSettings: ErgoSettings)( implicit val context: ActorRefFactory diff --git a/src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala index 89a7dbb280..dd645a8dc6 100644 --- a/src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala @@ -12,7 +12,7 @@ import org.ergoplatform.nodeView.wallet.ErgoAddressJsonEncoder import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings} import org.ergoplatform.{ErgoAddress, ErgoTreePredef, Pay2SAddress} import scorex.core.api.http.ApiResponse -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.data.ProveDlog import scala.concurrent.Future diff --git a/src/main/scala/org/ergoplatform/http/api/ScanApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ScanApiRoute.scala index 752b4eb112..abc407338d 100644 --- a/src/main/scala/org/ergoplatform/http/api/ScanApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/ScanApiRoute.scala @@ -14,8 +14,8 @@ import ScanEntities._ import org.ergoplatform.ErgoBox.R1 import org.ergoplatform.http.api.ApiError.BadRequest import org.ergoplatform.wallet.Constants.ScanId -import sigmastate.Values.ByteArrayConstant -import sigmastate.serialization.ErgoTreeSerializer +import sigma.ast.ByteArrayConstant +import sigma.serialization.ErgoTreeSerializer /** * This class contains methods to register / deregister and list external scans, and also to serve them. diff --git a/src/main/scala/org/ergoplatform/http/api/ScriptApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ScriptApiRoute.scala index 3ab560a3c1..6a2b614235 100644 --- a/src/main/scala/org/ergoplatform/http/api/ScriptApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/ScriptApiRoute.scala @@ -14,13 +14,12 @@ import org.ergoplatform.nodeView.wallet.requests.PaymentRequestDecoder import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings} import scorex.core.api.http.ApiResponse import scorex.util.encode.Base16 -import sigmastate.Values.{ByteArrayConstant, ErgoTree} -import sigmastate._ -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.ast.{ByteArrayConstant, ErgoTree} +import sigma.data.ProveDlog import sigmastate.eval.CompiletimeIRContext import sigmastate.interpreter.Interpreter import sigmastate.lang.{CompilerResult, SigmaCompiler} -import sigmastate.serialization.ValueSerializer +import sigma.serialization.ValueSerializer import scala.concurrent.Future import scala.concurrent.duration._ @@ -60,13 +59,13 @@ case class ScriptApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSettings) } private def compileSource(source: String, env: Map[String, Any]): Try[ErgoTree] = { - import sigmastate.Values._ + import sigma.ast._ val compiler = new SigmaCompiler(ergoSettings.chainSettings.addressPrefix) Try(compiler.compile(env, source)(new CompiletimeIRContext)).flatMap { case CompilerResult(_, _, _, script: Value[SSigmaProp.type@unchecked]) if script.tpe == SSigmaProp => - Success(script) + Success(ErgoTree.fromProposition(script)) case CompilerResult(_, _, _, script: Value[SBoolean.type@unchecked]) if script.tpe == SBoolean => - Success(script.toSigmaProp) + Success(ErgoTree.fromProposition(script.toSigmaProp)) case other => Failure(new Exception(s"Source compilation result is of type ${other.buildTree.tpe}, but `SBoolean` expected")) } diff --git a/src/main/scala/org/ergoplatform/http/api/TransactionsApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/TransactionsApiRoute.scala index 0cc95f24a3..489e8ac6aa 100644 --- a/src/main/scala/org/ergoplatform/http/api/TransactionsApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/TransactionsApiRoute.scala @@ -17,8 +17,8 @@ import org.ergoplatform.settings.{Algos, ErgoSettings, RESTApiSettings} import scorex.core.api.http.ApiResponse import scorex.crypto.authds.ADKey import scorex.util.encode.Base16 -import sigmastate.SType -import sigmastate.Values.EvaluatedValue +import sigma.ast.SType +import sigma.ast.EvaluatedValue import sigmastate.eval.Extensions.ArrayByteOps import scala.concurrent.Future diff --git a/src/main/scala/org/ergoplatform/http/api/requests/CryptoResult.scala b/src/main/scala/org/ergoplatform/http/api/requests/CryptoResult.scala index 0df36c67d7..beac5636ac 100644 --- a/src/main/scala/org/ergoplatform/http/api/requests/CryptoResult.scala +++ b/src/main/scala/org/ergoplatform/http/api/requests/CryptoResult.scala @@ -1,6 +1,6 @@ package org.ergoplatform.http.api.requests -import sigmastate.Values.SigmaBoolean +import sigma.data.SigmaBoolean /** * Result of reduction of ErgoTree for context provided (used in /script/executeWithContext) diff --git a/src/main/scala/org/ergoplatform/http/api/requests/HintExtractionRequest.scala b/src/main/scala/org/ergoplatform/http/api/requests/HintExtractionRequest.scala index e3e6162e63..799771ae36 100644 --- a/src/main/scala/org/ergoplatform/http/api/requests/HintExtractionRequest.scala +++ b/src/main/scala/org/ergoplatform/http/api/requests/HintExtractionRequest.scala @@ -1,7 +1,7 @@ package org.ergoplatform.http.api.requests import org.ergoplatform.modifiers.mempool.ErgoTransaction -import sigmastate.Values.SigmaBoolean +import sigma.data.SigmaBoolean /** * Represent a request for extracting prover hints from transaction. diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala index a42b50e6db..4530fa69e8 100644 --- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala +++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala @@ -27,12 +27,10 @@ import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoTreePredef, Input} import scorex.crypto.hash.Digest32 import scorex.util.encode.Base16 import scorex.util.{ModifierId, ScorexLogging} -import sigmastate.ErgoBoxRType -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.crypto.CryptoFacade -import sigmastate.eval.Extensions._ -import sigmastate.eval._ -import sigmastate.interpreter.ProverResult +import sigma.data.{Digest32Coll, ProveDlog} +import sigma.crypto.CryptoFacade +import sigma.eval.Extensions.EvalIterableOps +import sigma.interpreter.ProverResult import sigma.{Coll, Colls} import scala.annotation.tailrec @@ -745,8 +743,9 @@ object CandidateGenerator extends ScorexLogging { .filter(b => java.util.Arrays.equals(b.propositionBytes, propositionBytes) && !inputs.exists(i => java.util.Arrays.equals(i.boxId, b.id))) val feeTxOpt: Option[ErgoTransaction] = if (feeBoxes.nonEmpty) { val feeAmount = feeBoxes.map(_.value).sum - val feeAssets = - feeBoxes.toColl.flatMap(_.additionalTokens).take(MaxAssetsPerBox) + val feeAssets = feeBoxes + .flatMap(_.additionalTokens.toArray) + .toColl.take(MaxAssetsPerBox) val inputs = feeBoxes.map(b => new Input(b.id, ProverResult.empty)) val minerBox = new ErgoBoxCandidate(feeAmount, minerProp, nextHeight, feeAssets, Map()) diff --git a/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala b/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala index 732bf25805..b0829ee0f2 100644 --- a/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala +++ b/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala @@ -3,7 +3,7 @@ package org.ergoplatform.mining import org.ergoplatform.modifiers.history.header.Header import scorex.crypto.authds.ADDigest import scorex.crypto.hash.Digest32 -import sigmastate.crypto.CryptoConstants.EcPointType +import sigma.crypto.EcPointType import scala.util.{Random, Success, Try} diff --git a/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala b/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala index 82b8630abd..4b970ecdb2 100644 --- a/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala +++ b/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala @@ -10,7 +10,8 @@ import org.ergoplatform.settings.ErgoSettings import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.GetDataFromCurrentView import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.FullBlockApplied import scorex.util.ScorexLogging -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} +import sigma.data.ProveDlog +import sigmastate.crypto.DLogProtocol.DLogProverInput import scala.concurrent.duration._ import scala.util.{Failure, Success} diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala index dbda566f34..672c888bb3 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala @@ -15,7 +15,7 @@ import org.ergoplatform.nodeView.history.extra.IndexedTokenSerializer.uniqueId import org.ergoplatform.nodeView.history.storage.HistoryStorage import org.ergoplatform.settings.{Algos, CacheSettings, ChainSettings} import scorex.util.{ModifierId, ScorexLogging, bytesToId} -import sigmastate.Values.ErgoTree +import sigma.ast.ErgoTree import sigma.Extensions._ import java.nio.ByteBuffer diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoAddress.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoAddress.scala index c95acc381d..33e932a0b4 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoAddress.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoAddress.scala @@ -8,7 +8,7 @@ import org.ergoplatform.settings.Algos import org.ergoplatform.serialization.ErgoSerializer import scorex.util.{ModifierId, bytesToId} import scorex.util.serialization.{Reader, Writer} -import sigmastate.Values.ErgoTree +import sigma.ast.ErgoTree import scala.collection.mutable.ArrayBuffer diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala index e29b0fc04d..bcd0a3c75b 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala @@ -1,17 +1,17 @@ package org.ergoplatform.nodeView.history.extra -import org.ergoplatform.{ErgoAddressEncoder, ErgoBox} import org.ergoplatform.ErgoBox.{R4, R5, R6} -import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader} import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{ExtraIndexTypeId, fastIdToBytes} import org.ergoplatform.nodeView.history.extra.IndexedTokenSerializer.{ByteColl, uniqueId} -import org.ergoplatform.settings.Algos +import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader} import org.ergoplatform.serialization.ErgoSerializer -import scorex.util.{ModifierId, bytesToId} +import org.ergoplatform.settings.Algos +import org.ergoplatform.{ErgoAddressEncoder, ErgoBox} import scorex.util.serialization.{Reader, Writer} -import sigmastate.Values.CollectionConstant -import sigmastate.SByte +import scorex.util.{ModifierId, bytesToId} import sigma.Extensions._ +import sigma.ast.SByte +import sigma.ast.syntax.CollectionConstant import scala.collection.mutable.ArrayBuffer diff --git a/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala index 31362aa4d2..2dc8e87b83 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala @@ -22,10 +22,10 @@ import scorex.crypto.authds.avltree.batch.{Insert, Lookup, Remove} import scorex.crypto.authds.{ADDigest, ADValue} import scorex.util.encode.Base16 import scorex.util.{ModifierId, ScorexLogging, bytesToId} -import sigmastate.AtLeast -import sigmastate.Values.{ByteArrayConstant, ErgoTree, IntConstant, SigmaPropConstant} -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.serialization.ValueSerializer +import sigma.Colls +import sigma.ast._ +import sigma.data.ProveDlog +import sigma.serialization.ValueSerializer import spire.syntax.all.cfor import scala.annotation.tailrec @@ -205,15 +205,13 @@ object ErgoState extends ScorexLogging { ergoTree: ErgoTree, additionalTokens: Seq[(TokenId, Long)] = Seq.empty, additionalRegisters: AdditionalRegisters = Map.empty): ErgoBox = { - import sigmastate.eval._ - val creationHeight: Int = EmptyHistoryHeight val transactionId: ModifierId = ErgoBox.allZerosModifierId val boxIndex: Short = 0: Short new ErgoBox(value, ergoTree, - CostingSigmaDslBuilder.Colls.fromArray(additionalTokens.toArray[(TokenId, Long)]), + Colls.fromArray(additionalTokens.toArray[(TokenId, Long)]), additionalRegisters, transactionId, boxIndex, creationHeight) } diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActorMessages.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActorMessages.scala index c1f12a4941..6512cd6f50 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActorMessages.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActorMessages.scala @@ -15,8 +15,8 @@ import org.ergoplatform.wallet.interpreter.TransactionHintsBag import org.ergoplatform._ import org.ergoplatform.core.VersionTag import scorex.util.ModifierId -import sigmastate.Values.SigmaBoolean -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} +import sigma.data.{ProveDlog, SigmaBoolean} +import sigmastate.crypto.DLogProtocol.DLogProverInput import scala.util.Try /** diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletReader.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletReader.scala index ca8fa867d0..f4314528a6 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletReader.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletReader.scala @@ -18,7 +18,7 @@ import org.ergoplatform.wallet.interface4j.SecretString import org.ergoplatform.wallet.interpreter.TransactionHintsBag import org.ergoplatform.{ErgoBox, NodeViewComponent, P2PKAddress} import scorex.util.ModifierId -import sigmastate.Values.SigmaBoolean +import sigma.data.SigmaBoolean import sigmastate.crypto.DLogProtocol.DLogProverInput import java.util.concurrent.TimeUnit diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletService.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletService.scala index b84402e288..505c4ec4b6 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletService.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletService.scala @@ -22,7 +22,7 @@ import org.ergoplatform.wallet.secrets.JsonSecretStorage import org.ergoplatform.wallet.settings.SecretStorageSettings import org.ergoplatform.wallet.utils.FileUtils import scorex.util.ModifierId -import sigmastate.Values.SigmaBoolean +import sigma.data.SigmaBoolean import sigmastate.crypto.DLogProtocol.DLogProverInput import sigma.Extensions.CollBytesOps @@ -677,4 +677,4 @@ class ErgoWalletServiceImpl(override val ergoSettings: ErgoSettings) extends Erg .map(ErgoTransaction.apply) } -} \ No newline at end of file +} diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSupport.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSupport.scala index 2854306ddd..4ab8f3f07f 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSupport.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSupport.scala @@ -21,11 +21,11 @@ import org.ergoplatform.wallet.mnemonic.Mnemonic import org.ergoplatform.wallet.transactions.TransactionBuilder import scorex.util.ScorexLogging import sigma.Colls -import sigmastate.Values.ByteArrayConstant -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.ast.{ByteArrayConstant, ErgoTree} +import sigma.data.ProveDlog import sigmastate.eval.Extensions._ -import sigmastate.eval._ import sigmastate.utils.Extensions._ +import sigma.eval.Extensions.EvalIterableOps import scala.util.{Failure, Success, Try} @@ -255,7 +255,7 @@ trait ErgoWalletSupport extends ScorexLogging { // todo: is this extra check needed ? val reemissionTokenId = ergoSettings.chainSettings.reemission.reemissionTokenId val assets = changeBox.tokens.filterKeys(_ != reemissionTokenId).map(t => t._1.toTokenId -> t._2).toIndexedSeq - new ErgoBoxCandidate(changeBox.value, changeAddressOpt.get, walletHeight, assets.toColl) + new ErgoBoxCandidate(changeBox.value, ErgoTree.fromSigmaBoolean(changeAddressOpt.get), walletHeight, assets.toColl) } val inputBoxes = selectionResult.inputBoxes.toIndexedSeq new UnsignedErgoTransaction( diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/IdUtils.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/IdUtils.scala index a3040f805c..1652fd3162 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/IdUtils.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/IdUtils.scala @@ -4,8 +4,8 @@ import org.ergoplatform.ErgoBox.{BoxId, TokenId} import org.ergoplatform.settings.Algos import scorex.crypto.authds.ADKey import scorex.util.ModifierId -import sigmastate.eval.Digest32Coll -import sigmastate.eval.Extensions.ArrayOps +import sigma.data.Digest32Coll +import sigma.Extensions.ArrayOps import supertagged.TaggedType object IdUtils { diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/WalletCache.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/WalletCache.scala index 4ead415b3b..d3701fa4cc 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/WalletCache.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/WalletCache.scala @@ -4,7 +4,7 @@ import com.google.common.hash.{BloomFilter, Funnels} import org.ergoplatform.sdk.wallet.secrets.ExtendedPublicKey import org.ergoplatform.settings.ErgoSettings import org.ergoplatform.{ErgoAddressEncoder, ErgoTreePredef, P2PKAddress} -import sigmastate.Values +import sigma.ast.ErgoTree import sigmastate.eval._ import scala.util.Try @@ -20,7 +20,7 @@ final case class WalletCache(publicKeyAddresses: Seq[P2PKAddress], implicit val addressEncoder: ErgoAddressEncoder = settings.addressEncoder // Mining rewards are being tracked only if mining = true in config - private val miningScripts: Seq[Values.ErgoTree] = { + private val miningScripts: Seq[ErgoTree] = { if (settings.nodeSettings.mining) { WalletCache.miningScripts(trackedPubKeys, settings) } else { @@ -47,7 +47,7 @@ final case class WalletCache(publicKeyAddresses: Seq[P2PKAddress], object WalletCache { def miningScripts(trackedPubKeys: Seq[ExtendedPublicKey], - settings: ErgoSettings): Seq[Values.ErgoTree] = { + settings: ErgoSettings): Seq[ErgoTree] = { trackedPubKeys.map { pk => ErgoTreePredef.rewardOutputScript(settings.miningRewardDelay, pk.key) } diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorage.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorage.scala index 2f52c218f0..09eb04bc2f 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorage.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorage.scala @@ -10,7 +10,7 @@ import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId} import scorex.crypto.hash.Blake2b256 import scorex.db.{LDBFactory, LDBKVStore} import scorex.util.ScorexLogging -import sigmastate.serialization.SigmaSerializer +import sigma.serialization.SigmaSerializer import java.io.File import scala.util.{Failure, Success, Try} diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/AssetIssueRequest.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/AssetIssueRequest.scala index 0dd6fd72d0..c46b69cb45 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/AssetIssueRequest.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/AssetIssueRequest.scala @@ -7,8 +7,7 @@ import org.ergoplatform.ErgoBox.NonMandatoryRegisterId import org.ergoplatform.http.api.ApiCodecs import org.ergoplatform.nodeView.wallet.ErgoAddressJsonEncoder import org.ergoplatform.settings.ErgoSettings -import sigmastate.SType -import sigmastate.Values.EvaluatedValue +import sigma.ast._ /** * Request for new asset issuing. diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/PaymentRequest.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/PaymentRequest.scala index 9b44cdccb8..ff17cd8efe 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/PaymentRequest.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/PaymentRequest.scala @@ -7,8 +7,7 @@ import org.ergoplatform.modifiers.mempool.ErgoTransaction._ import org.ergoplatform.nodeView.wallet.ErgoAddressJsonEncoder import org.ergoplatform.settings.ErgoSettings import org.ergoplatform.{ErgoAddress, ErgoBox} -import sigmastate.SType -import sigmastate.Values.EvaluatedValue +import sigma.ast.{SType, EvaluatedValue} /** * A payment request contains an address (probably containing script), value, assets, additional registers. diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicate.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicate.scala index 133c1736ef..b9c3b4c30f 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicate.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicate.scala @@ -1,8 +1,8 @@ package org.ergoplatform.nodeView.wallet.scanning import org.ergoplatform.ErgoBox -import sigmastate.Values.EvaluatedValue -import sigmastate.{SType, Values} +import sigma.ast.EvaluatedValue +import sigma.ast._ import sigma.Extensions._ /** @@ -26,10 +26,10 @@ case class ContainsScanningPredicate(regId: ErgoBox.RegisterId, override def filter(box: ErgoBox): Boolean = { value match { - case Values.ByteArrayConstant(bytes) => + case ByteArrayConstant(bytes) => box.get(regId).exists { _ match { - case Values.ByteArrayConstant(arr) => arr.toArray.containsSlice(bytes.toArray) + case ByteArrayConstant(arr) => arr.toArray.containsSlice(bytes.toArray) case _ => false } } @@ -59,42 +59,42 @@ case class EqualsScanningPredicate(regId: ErgoBox.RegisterId, value: EvaluatedVa //todo: try to remove boilerplate below override def filter(box: ErgoBox): Boolean = { value match { - case Values.ByteArrayConstant(bytes) => + case ByteArrayConstant(bytes) => if(box.get(regId).isDefined && box.get(regId).get.tpe.equals(value.tpe)) { box.get(regId).exists { _ match { - case Values.ByteArrayConstant(arr) => arr.toArray.sameElements(bytes.toArray) + case ByteArrayConstant(arr) => arr.toArray.sameElements(bytes.toArray) case _ => false } } } else { false } - case Values.GroupElementConstant(groupElement) => + case GroupElementConstant(groupElement) => box.get(regId).exists { _ match { - case Values.GroupElementConstant(ge) => groupElement == ge + case GroupElementConstant(ge) => groupElement == ge case _ => false } } - case Values.BooleanConstant(bool) => + case BooleanConstant(bool) => box.get(regId).exists { _ match { - case Values.BooleanConstant(b) => bool == b + case BooleanConstant(b) => bool == b case _ => false } } - case Values.IntConstant(int) => + case IntConstant(int) => box.get(regId).exists { _ match { - case Values.IntConstant(i) => int == i + case IntConstant(i) => int == i case _ => false } } - case Values.LongConstant(long) => + case LongConstant(long) => box.get(regId).exists { _ match { - case Values.IntConstant(l) => long == l + case IntConstant(l) => long == l case _ => false } } diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecs.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecs.scala index c57b4923ff..8944686ab1 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecs.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecs.scala @@ -5,9 +5,8 @@ import io.circe.{Decoder, Encoder, Json} import org.ergoplatform.ErgoBox import org.ergoplatform.ErgoBox.RegisterId import org.ergoplatform.http.api.ApiCodecs -import sigmastate.SType -import sigmastate.Values.EvaluatedValue import sigma.Extensions._ +import sigma.ast.{EvaluatedValue, SType} object ScanningPredicateJsonCodecs extends ApiCodecs { diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializer.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializer.scala index 330c071373..f2b8cec9cd 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializer.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializer.scala @@ -5,10 +5,9 @@ import org.ergoplatform.ErgoBox.RegisterId import org.ergoplatform.serialization.ErgoSerializer import scorex.util.Extensions._ import scorex.util.serialization.{Reader, Writer} -import sigmastate.SType -import sigmastate.Values.EvaluatedValue +import sigma.ast._ import sigmastate.eval.Extensions.ArrayByteOps -import sigmastate.serialization.ValueSerializer +import sigma.serialization.ValueSerializer object ScanningPredicateSerializer extends ErgoSerializer[ScanningPredicate] { diff --git a/src/main/scala/org/ergoplatform/reemission/ReemissionRulesUtils.scala b/src/main/scala/org/ergoplatform/reemission/ReemissionRulesUtils.scala index f149097489..1a86ff0751 100644 --- a/src/main/scala/org/ergoplatform/reemission/ReemissionRulesUtils.scala +++ b/src/main/scala/org/ergoplatform/reemission/ReemissionRulesUtils.scala @@ -3,10 +3,9 @@ package org.ergoplatform.reemission import org.ergoplatform.mining.emission.EmissionRules import org.ergoplatform.settings.ErgoSettingsReader import org.ergoplatform.{ErgoAddressEncoder, Pay2SAddress} -import sigmastate.SBoolean -import sigmastate.Values.Value +import sigma.ast._ import sigmastate.eval.CompiletimeIRContext -import sigmastate.lang.{CompilerSettings, SigmaCompiler, TransformingSigmaBuilder} +import sigmastate.lang.{CompilerSettings, SigmaCompiler} import scala.util.Try @@ -36,7 +35,7 @@ object ReemissionRulesUtils { val compiler = SigmaCompiler(CompilerSettings(networkPrefix, TransformingSigmaBuilder, lowerMethodCalls = true)) val compiled = Try(compiler.compile(Map.empty, source)(new CompiletimeIRContext)).get.asInstanceOf[Value[SBoolean.type]].toSigmaProp - Pay2SAddress.apply(compiled) + Pay2SAddress.apply(ErgoTree.fromProposition(compiled)) } def main(args: Array[String]): Unit = { diff --git a/src/main/scala/org/ergoplatform/settings/ErgoSettings.scala b/src/main/scala/org/ergoplatform/settings/ErgoSettings.scala index 8ada7c5c16..e0e9136bdd 100644 --- a/src/main/scala/org/ergoplatform/settings/ErgoSettings.scala +++ b/src/main/scala/org/ergoplatform/settings/ErgoSettings.scala @@ -3,7 +3,7 @@ package org.ergoplatform.settings import org.ergoplatform.mining.groupElemFromBytes import org.ergoplatform.{ErgoAddressEncoder, P2PKAddress} import scorex.util.encode.Base16 -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.data.ProveDlog import scala.util.Try diff --git a/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala index c3a1c33851..4898defea9 100644 --- a/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala @@ -17,7 +17,7 @@ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scorex.crypto.authds.ADKey import scorex.utils.Random -import sigmastate.Values.ByteArrayConstant +import sigma.ast.ByteArrayConstant import scala.concurrent.duration._ import scala.util.Try diff --git a/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala index ff4b372c56..b5cf0e52a0 100644 --- a/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala @@ -13,10 +13,9 @@ import org.ergoplatform.http.api.ScriptApiRoute import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scorex.util.encode.Base16 -import sigmastate.SByte -import sigmastate.Values.{CollectionConstant, ErgoTree, TrueLeaf} -import sigmastate.serialization.{ErgoTreeSerializer, ValueSerializer} - +import sigma.ast.syntax.CollectionConstant +import sigma.ast.{ErgoTree, SByte, TrueLeaf} +import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} class ScriptApiRouteSpec extends AnyFlatSpec with Matchers @@ -103,7 +102,7 @@ class ScriptApiRouteSpec extends AnyFlatSpec val p2pk = "3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN" Get(s"$prefix/$suffix/$p2pk") ~> route ~> check(assertion(responseAs[Json], p2pk)) - val script = TrueLeaf + val script = TrueLeaf.toSigmaProp val tree = ErgoTree.fromProposition(script) val p2sh = Pay2SHAddress.apply(tree).toString() @@ -125,7 +124,7 @@ class ScriptApiRouteSpec extends AnyFlatSpec val bac = ValueSerializer.deserialize(vbs).asInstanceOf[CollectionConstant[SByte.type]] - val bs = bac.value.toArray.map(_.byteValue()) + val bs = bac.value.toArray.map(b => b.byteValue()) val tree = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bs) @@ -140,7 +139,7 @@ class ScriptApiRouteSpec extends AnyFlatSpec val p2sh = "rbcrmKEYduUvADj9Ts3dSVSG27h54pgrq5fPuwB" Get(s"$prefix/$suffix/$p2sh") ~> route ~> check(assertion(responseAs[Json], p2sh)) - val script = TrueLeaf + val script = TrueLeaf.toSigmaProp val tree = ErgoTree.fromProposition(script) val p2s = addressEncoder.toString(addressEncoder.fromProposition(tree).get) p2s shouldBe "Ms7smJwLGbUAjuWQ" diff --git a/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala index 2708b93390..e8955966dc 100644 --- a/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala @@ -17,11 +17,10 @@ import org.ergoplatform.{DataInput, ErgoBox, ErgoBoxCandidate, Input} import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scorex.util.encode.Base16 -import sigmastate.SType -import sigmastate.Values.{ByteArrayConstant, EvaluatedValue} import sigmastate.eval.Extensions._ -import sigmastate.eval._ import sigma.Extensions._ +import sigma.eval.Extensions.EvalIterableOps +import sigma.ast.{ByteArrayConstant, EvaluatedValue, SType} import java.net.InetSocketAddress import scala.concurrent.duration._ diff --git a/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala index 57503fb23a..029a1710be 100644 --- a/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala @@ -13,7 +13,8 @@ import org.ergoplatform.settings.RESTApiSettings import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scorex.util.encode.Base16 -import sigmastate.serialization.ErgoTreeSerializer +import sigma.serialization.ErgoTreeSerializer +import sigma.serialization.ErgoTreeSerializer import scala.concurrent.duration._ diff --git a/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala b/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala index 749f9f41de..b38c72ec1d 100644 --- a/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala +++ b/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala @@ -14,12 +14,12 @@ import org.ergoplatform.utils.fixtures.NodeViewFixture import org.ergoplatform.utils.{ErgoTestHelpers, MempoolTestHelpers, NodeViewTestOps, RandomWrapper} import org.scalatest.flatspec.AnyFlatSpec import scorex.core.network.NetworkController.ReceivableMessages.SendToNetwork -import sigmastate.Values.ErgoTree +import sigma.ast.ErgoTree +import sigma.ast.syntax.ValueOps import sigmastate.eval.{IRContext, RuntimeIRContext} import sigmastate.interpreter.Interpreter.emptyEnv import sigmastate.lang.SigmaCompiler -import sigmastate.lang.Terms.ValueOps -import sigmastate.serialization.ErgoTreeSerializer +import sigma.serialization.ErgoTreeSerializer import scala.concurrent.duration._ @@ -64,7 +64,7 @@ class MempoolAuditorSpec extends AnyFlatSpec with NodeViewTestOps with ErgoTestH val validTx = validTransactionFromBoxes(boxes.toIndexedSeq, outputsProposition = tree) - val temporarilyValidTx = validTransactionFromBoxes(validTx.outputs, outputsProposition = proveDlogGen.sample.get) + val temporarilyValidTx = validTransactionFromBoxes(validTx.outputs, outputsProposition = ErgoTree.fromSigmaBoolean(proveDlogGen.sample.get)) subscribeEvents(classOf[FailedTransaction]) nodeViewHolderRef ! LocallyGeneratedTransaction(UnconfirmedTransaction(validTx, None)) diff --git a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala index 4917d4d104..65249cc0b7 100644 --- a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala +++ b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala @@ -7,7 +7,7 @@ import org.ergoplatform.settings.MonetarySettings import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} import org.ergoplatform.wallet.interpreter.ErgoInterpreter import org.scalacheck.Gen -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.data.ProveDlog import scala.concurrent.duration._ diff --git a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala index d94938f591..405a70afec 100644 --- a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala +++ b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala @@ -19,7 +19,8 @@ import org.ergoplatform.utils.ErgoTestHelpers import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoTreePredef, Input} import org.scalatest.concurrent.Eventually import org.scalatest.flatspec.AnyFlatSpec -import sigmastate.crypto.DLogProtocol +import sigma.ast.ErgoTree +import sigma.data.ProveDlog import sigmastate.crypto.DLogProtocol.DLogProverInput import scala.concurrent.duration._ @@ -197,7 +198,7 @@ class CandidateGeneratorSpec extends AnyFlatSpec with ErgoTestHelpers with Event } // build new transaction that uses miner's reward as input - val prop: DLogProtocol.ProveDlog = + val prop: ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test".getBytes())).publicImage val newlyMinedBlock = readers.h.bestFullBlockOpt.get val rewardBox: ErgoBox = newlyMinedBlock.transactions.last.outputs.last @@ -207,7 +208,7 @@ class CandidateGeneratorSpec extends AnyFlatSpec with ErgoTestHelpers with Event val input = Input(rewardBox.id, emptyProverResult) val outputs = IndexedSeq( - new ErgoBoxCandidate(rewardBox.value, prop, readers.s.stateContext.currentHeight) + new ErgoBoxCandidate(rewardBox.value, ErgoTree.fromSigmaBoolean(prop), readers.s.stateContext.currentHeight) ) val unsignedTx = new UnsignedErgoTransaction(IndexedSeq(input), IndexedSeq(), outputs) diff --git a/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala b/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala index c86eea5209..1c022a69ee 100644 --- a/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala +++ b/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala @@ -24,9 +24,8 @@ import org.ergoplatform.wallet.interpreter.ErgoInterpreter import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoTreePredef, Input} import org.scalatest.concurrent.Eventually import org.scalatest.flatspec.AnyFlatSpec -import sigmastate.SigmaAnd -import sigmastate.Values.{ErgoTree, SigmaPropConstant} -import sigmastate.crypto.DLogProtocol +import sigma.ast.{ErgoTree, SigmaAnd, SigmaPropConstant} +import sigma.data.ProveDlog import sigmastate.crypto.DLogProtocol.DLogProverInput import scala.annotation.tailrec @@ -63,10 +62,13 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen val testProbe = new TestProbe(system) system.eventStream.subscribe(testProbe.ref, newBlockSignal) val ergoSettings: ErgoSettings = defaultSettings.copy(directory = createTempDir.getAbsolutePath) - val complexScript: ErgoTree = (0 until 100).foldLeft(SigmaAnd(SigmaPropConstant(defaultMinerPk), SigmaPropConstant(defaultMinerPk))) { (l, _) => - SigmaAnd(SigmaPropConstant(defaultMinerPk), l) + val complexScript: ErgoTree = { + val start = SigmaAnd(SigmaPropConstant(defaultMinerPk), SigmaPropConstant(defaultMinerPk)) + val tree = ErgoTree.fromProposition((0 until 100).foldLeft(start) { (l, _) => + SigmaAnd(SigmaPropConstant(defaultMinerPk), l) + }) + tree } - complexScript.complexity shouldBe 28077 val nodeViewHolderRef: ActorRef = ErgoNodeViewRef(ergoSettings) val readersHolderRef: ActorRef = ErgoReadersHolderRef(nodeViewHolderRef) @@ -173,7 +175,7 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen val feeBox = new ErgoBoxCandidate(boxToSend.value / desiredSize, feeProp, r.s.stateContext.currentHeight) val outputs = (1 until desiredSize).map { _ => - new ErgoBoxCandidate(boxToSend.value / desiredSize, defaultMinerPk, r.s.stateContext.currentHeight) + new ErgoBoxCandidate(boxToSend.value / desiredSize, ErgoTree.fromSigmaBoolean(defaultMinerPk), r.s.stateContext.currentHeight) } val unsignedTx = new UnsignedErgoTransaction(inputs, IndexedSeq(), feeBox +: outputs) ErgoTransaction( @@ -237,18 +239,18 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - val prop1: DLogProtocol.ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test1".getBytes())).publicImage - val prop2: DLogProtocol.ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test2".getBytes())).publicImage + val prop1: ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test1".getBytes())).publicImage + val prop2: ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test2".getBytes())).publicImage val boxToDoubleSpend: ErgoBox = r.h.bestFullBlockOpt.get.transactions.last.outputs.last boxToDoubleSpend.propositionBytes shouldBe ErgoTreePredef.rewardOutputScript(emission.settings.minerRewardDelay, defaultMinerPk).bytes val input = Input(boxToDoubleSpend.id, emptyProverResult) - val outputs1 = IndexedSeq(new ErgoBoxCandidate(boxToDoubleSpend.value, prop1, r.s.stateContext.currentHeight)) + val outputs1 = IndexedSeq(new ErgoBoxCandidate(boxToDoubleSpend.value, ErgoTree.fromSigmaBoolean(prop1), r.s.stateContext.currentHeight)) val unsignedTx1 = new UnsignedErgoTransaction(IndexedSeq(input), IndexedSeq(), outputs1) val tx1 = defaultProver.sign(unsignedTx1, IndexedSeq(boxToDoubleSpend), IndexedSeq(), r.s.stateContext).get - val outputs2 = IndexedSeq(new ErgoBoxCandidate(boxToDoubleSpend.value, prop2, r.s.stateContext.currentHeight)) + val outputs2 = IndexedSeq(new ErgoBoxCandidate(boxToDoubleSpend.value, ErgoTree.fromSigmaBoolean(prop2), r.s.stateContext.currentHeight)) val unsignedTx2 = new UnsignedErgoTransaction(IndexedSeq(input), IndexedSeq(), outputs2) val tx2 = ErgoTransaction(defaultProver.sign(unsignedTx2, IndexedSeq(boxToDoubleSpend), IndexedSeq(), r.s.stateContext).get) @@ -332,18 +334,18 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - val prop1: DLogProtocol.ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test1".getBytes())).publicImage - val prop2: DLogProtocol.ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test2".getBytes())).publicImage + val prop1: ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test1".getBytes())).publicImage + val prop2: ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test2".getBytes())).publicImage val mBox: ErgoBox = r.h.bestFullBlockOpt.get.transactions.last.outputs.last val mInput = Input(mBox.id, emptyProverResult) - val outputs1 = IndexedSeq(new ErgoBoxCandidate(mBox.value, prop1, r.s.stateContext.currentHeight)) + val outputs1 = IndexedSeq(new ErgoBoxCandidate(mBox.value, ErgoTree.fromSigmaBoolean(prop1), r.s.stateContext.currentHeight)) val unsignedTx1 = new UnsignedErgoTransaction(IndexedSeq(mInput), IndexedSeq(), outputs1) val mandatoryTxLike1 = defaultProver.sign(unsignedTx1, IndexedSeq(mBox), IndexedSeq(), r.s.stateContext).get val mandatoryTx1 = ErgoTransaction(mandatoryTxLike1) - val outputs2 = IndexedSeq(new ErgoBoxCandidate(mBox.value, prop2, r.s.stateContext.currentHeight)) + val outputs2 = IndexedSeq(new ErgoBoxCandidate(mBox.value, ErgoTree.fromSigmaBoolean(prop2), r.s.stateContext.currentHeight)) val unsignedTx2 = new UnsignedErgoTransaction(IndexedSeq(mInput), IndexedSeq(), outputs2) val mandatoryTxLike2 = defaultProver.sign(unsignedTx2, IndexedSeq(mBox), IndexedSeq(), r.s.stateContext).get val mandatoryTx2 = ErgoTransaction(mandatoryTxLike2) diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala index 371b356384..b3a6d7431a 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala @@ -20,13 +20,12 @@ import scorex.crypto.hash.Blake2b256 import scorex.util.encode.Base16 import scorex.util.{ModifierId, bytesToId} import sigma.Colls -import sigmastate.AND -import sigmastate.Values.{ByteArrayConstant, ByteConstant, IntConstant, LongArrayConstant, SigmaPropConstant, TrueLeaf} -import sigmastate.crypto.CryptoConstants -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.eval._ +import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast._ +import sigma.crypto.CryptoConstants +import sigma.data.ProveDlog import sigmastate.helpers.TestingHelpers._ -import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigma.interpreter.{ContextExtension, ProverResult} import sigmastate.eval.Extensions._ import scala.util.{Random, Try} @@ -109,7 +108,7 @@ class ErgoTransactionSpec extends ErgoPropertyTest with ErgoTestConstants { new ProverResult(Base16.decode("5aea4d78a234c35accacdf8996b0af5b51e26fee29ea5c05468f23707d31c0df39400127391cd57a70eb856710db48bb9833606e0bf90340").get, new ContextExtension(Map()))), ) val outputCandidates: IndexedSeq[ErgoBoxCandidate] = IndexedSeq( - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, Map()), + new ErgoBoxCandidate(1000000000L, ErgoTree.fromSigmaBoolean(minerPk), height, Colls.emptyColl, Map()), new ErgoBoxCandidate(1000000L, settings.chainSettings.monetary.feeProposition, height, Colls.emptyColl, Map()) ) val tx = ErgoTransaction(inputs: IndexedSeq[Input], outputCandidates: IndexedSeq[ErgoBoxCandidate]) @@ -123,7 +122,7 @@ class ErgoTransactionSpec extends ErgoPropertyTest with ErgoTestConstants { // tx with registers in outputs val outputCandidates2: IndexedSeq[ErgoBoxCandidate] = IndexedSeq( - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, + new ErgoBoxCandidate(1000000000L, ErgoTree.fromSigmaBoolean(minerPk), height, Colls.emptyColl, Map( R6 -> IntConstant(10), R4 -> ByteConstant(1), @@ -131,7 +130,7 @@ class ErgoTransactionSpec extends ErgoPropertyTest with ErgoTestConstants { R7 -> LongArrayConstant(Array(1L, 2L, 1234123L)), R8 -> ByteArrayConstant(Base16.decode("123456123456123456123456123456123456123456123456123456123456123456").get), )), - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, Map()) + new ErgoBoxCandidate(1000000000L, ErgoTree.fromSigmaBoolean(minerPk), height, Colls.emptyColl, Map()) ) val tx2 = ErgoTransaction(inputs: IndexedSeq[Input], outputCandidates2: IndexedSeq[ErgoBoxCandidate]) @@ -436,7 +435,7 @@ class ErgoTransactionSpec extends ErgoPropertyTest with ErgoTestConstants { forAll(smallPositiveInt) { inputsNum => - val nonTrivialTrueGen = Gen.const(AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp.treeWithSegregation) + val nonTrivialTrueGen = Gen.const(ErgoTree.withSegregation(ZeroHeader, AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp)) val gen = validErgoTransactionGenTemplate(0, 0, inputsNum, nonTrivialTrueGen) val (from, tx) = gen.sample.get tx.statelessValidity().isSuccess shouldBe true diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala index 38c67cad88..3dbbab6f4a 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala @@ -8,11 +8,10 @@ import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input} import org.scalatest.Assertion import scorex.util.encode.Base16 import sigma.Colls -import sigmastate.Values.{ErgoTree, ShortConstant} -import sigmastate.interpreter.{ContextExtension, ProverResult} -import sigmastate.eval._ +import sigma.ast.{ErgoTree, ShortConstant} +import sigma.interpreter.{ContextExtension, ProverResult} import sigmastate.helpers.TestingHelpers._ -import sigmastate.serialization.ErgoTreeSerializer +import sigma.serialization.ErgoTreeSerializer class ExpirationSpecification extends ErgoPropertyTest { diff --git a/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala b/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala index 8270804c48..1ca645786b 100644 --- a/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala +++ b/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala @@ -9,7 +9,7 @@ import scorex.crypto.authds.ADDigest import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import scorex.util.encode.Base16 -import sigmastate.crypto.CryptoConstants.EcPointType +import sigma.crypto.EcPointType import java.nio.ByteBuffer diff --git a/src/test/scala/org/ergoplatform/nodeView/history/extra/ChainGenerator.scala b/src/test/scala/org/ergoplatform/nodeView/history/extra/ChainGenerator.scala index 144305ab33..b0c5cae38f 100644 --- a/src/test/scala/org/ergoplatform/nodeView/history/extra/ChainGenerator.scala +++ b/src/test/scala/org/ergoplatform/nodeView/history/extra/ChainGenerator.scala @@ -15,11 +15,10 @@ import org.ergoplatform.nodeView.state.{ErgoState, ErgoStateContext, UtxoState, import org.ergoplatform.utils.ErgoTestHelpers import org.ergoplatform._ import scorex.util.ModifierId +import sigma.ast.ErgoTree import sigma.{Coll, Colls} -import sigmastate.Values -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.data.ProveDlog import sigmastate.eval.Extensions._ -import sigmastate.eval._ import java.io.File import scala.annotation.tailrec @@ -36,8 +35,8 @@ object ChainGenerator extends ErgoTestHelpers { val RewardDelay: Int = initSettings.chainSettings.monetary.minerRewardDelay val MaxTxsPerBlock: Int = 10 val minerPk: ProveDlog = defaultProver.hdKeys.head.publicImage - val selfAddressScript: Values.ErgoTree = P2PKAddress(minerPk).script - val minerProp: Values.ErgoTree = ErgoTreePredef.rewardOutputScript(RewardDelay, minerPk) + val selfAddressScript: ErgoTree = P2PKAddress(minerPk).script + val minerProp: ErgoTree = ErgoTreePredef.rewardOutputScript(RewardDelay, minerPk) val votingEpochLength: Height = votingSettings.votingLength val protocolVersion: Byte = initSettings.chainSettings.protocolVersion val minimalSuffix = 2 diff --git a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala index b705ec11ad..38e3283e3d 100644 --- a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala @@ -1,16 +1,17 @@ package org.ergoplatform.nodeView.mempool -import org.ergoplatform.{ErgoBoxCandidate, Input} -import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.{SortingOption, ProcessingOutcome} import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} +import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.{ProcessingOutcome, SortingOption} import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.settings.ErgoSettings import org.ergoplatform.utils.ErgoTestHelpers import org.ergoplatform.utils.generators.ErgoGenerators +import org.ergoplatform.{ErgoBoxCandidate, Input} import org.scalatest.flatspec.AnyFlatSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigmastate.Values.{ByteArrayConstant, TrueLeaf} -import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast.{ByteArrayConstant, ErgoTree, TrueLeaf} +import sigma.interpreter.{ContextExtension, ProverResult} class ErgoMemPoolSpec extends AnyFlatSpec with ErgoGenerators @@ -98,8 +99,9 @@ class ErgoMemPoolSpec extends AnyFlatSpec val wus = WrappedUtxoState(us, bh, settings, extendedParameters).applyModifier(genesis)(_ => ()).get val feeProp = settings.chainSettings.monetary.feeProposition + val trueTree = ErgoTree.withSegregation(ZeroHeader, TrueLeaf.toSigmaProp) val inputBox = wus.takeBoxes(100).collectFirst{ - case box if box.ergoTree == TrueLeaf.toSigmaProp.treeWithSegregation => box + case box if box.ergoTree == trueTree => box }.get val feeOut = new ErgoBoxCandidate(inputBox.value, feeProp, creationHeight = 0) diff --git a/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala b/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala index 7f2f6b7cca..ac116a318d 100644 --- a/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala @@ -5,15 +5,15 @@ import org.ergoplatform.ErgoTreePredef.boxCreationHeight import org.ergoplatform.nodeView.state.{BoxHolder, ErgoState, UtxoState} import org.ergoplatform.settings.Algos import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} -import org.ergoplatform.{ErgoBox, ErgoTreePredef, Height, Self} +import org.ergoplatform.{ErgoBox, ErgoTreePredef} import scorex.crypto.authds.avltree.batch.Remove -import sigmastate.Values._ +import sigma.ast.syntax.ValueOps +import sigma.ast.{TransformingSigmaBuilder, _} import sigmastate._ -import sigmastate.crypto.CryptoConstants.dlogGroup -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.crypto.CryptoConstants.dlogGroup +import sigma.data.ProveDlog import sigmastate.eval.{CompiletimeIRContext, IRContext} -import sigmastate.lang.Terms._ -import sigmastate.lang.{CompilerSettings, SigmaCompiler, TransformingSigmaBuilder} +import sigmastate.lang.{CompilerSettings, SigmaCompiler} import scala.util.Try @@ -25,19 +25,21 @@ class ScriptsSpec extends ErgoPropertyTest { val delta = emission.settings.minerRewardDelay val fixedBox: ErgoBox = ergoBoxGen(fromString("1 == 1"), heightGen = 0).sample.get implicit lazy val context: IRContext = new CompiletimeIRContext + val trueTree = ErgoTree.fromProposition(TrueLeaf.toSigmaProp) + val falseTree = ErgoTree.fromProposition(FalseLeaf.toSigmaProp) property("simple operations without cryptography") { // true/false - applyBlockSpendingScript(Values.TrueLeaf.toSigmaProp) shouldBe 'success - applyBlockSpendingScript(Values.FalseLeaf.toSigmaProp) shouldBe 'failure + applyBlockSpendingScript(trueTree) shouldBe 'success + applyBlockSpendingScript(falseTree) shouldBe 'failure // eq - applyBlockSpendingScript(EQ(IntConstant(1), IntConstant(1)).toSigmaProp) shouldBe 'success - applyBlockSpendingScript(EQ(IntConstant(1), IntConstant(2)).toSigmaProp) shouldBe 'failure + applyBlockSpendingScript(ErgoTree.fromProposition(EQ(IntConstant(1), IntConstant(1)).toSigmaProp)) shouldBe 'success + applyBlockSpendingScript(ErgoTree.fromProposition(EQ(IntConstant(1), IntConstant(2)).toSigmaProp)) shouldBe 'failure // math - applyBlockSpendingScript(EQ(Plus(1, 2), Minus(6, 3)).toSigmaProp) shouldBe 'success - applyBlockSpendingScript(EQ(Multiply(1, 2), Divide(7, 3)).toSigmaProp) shouldBe 'success + applyBlockSpendingScript(ErgoTree.fromProposition(EQ(Plus(1, 2), Minus(6, 3)).toSigmaProp)) shouldBe 'success + applyBlockSpendingScript(ErgoTree.fromProposition(EQ(Multiply(1, 2), Divide(7, 3)).toSigmaProp)) shouldBe 'success // context - applyBlockSpendingScript(EQ(IntConstant(1), Height).toSigmaProp) shouldBe 'success + applyBlockSpendingScript(ErgoTree.fromProposition(EQ(IntConstant(1), Height).toSigmaProp)) shouldBe 'success applyBlockSpendingScript(fromString("CONTEXT.preHeader.height == 1")) shouldBe 'success applyBlockSpendingScript(fromString("CONTEXT.headers.size == 0")) shouldBe 'success applyBlockSpendingScript(fromString(s"CONTEXT.dataInputs.exists{ (box: Box) => box.value == ${fixedBox.value}L}")) shouldBe 'success @@ -45,23 +47,25 @@ class ScriptsSpec extends ErgoPropertyTest { } property("simple crypto") { - applyBlockSpendingScript(defaultMinerPk) shouldBe 'success - applyBlockSpendingScript(SigmaAnd(defaultProver.hdKeys.map(s => SigmaPropConstant(s.publicImage)))) shouldBe 'success - applyBlockSpendingScript(SigmaAnd(defaultMinerPk, ProveDlog(dlogGroup.generator))) shouldBe 'failure - applyBlockSpendingScript(SigmaOr(defaultMinerPk, ProveDlog(dlogGroup.generator))) shouldBe 'success + applyBlockSpendingScript(ErgoTree.fromSigmaBoolean(defaultMinerPk)) shouldBe 'success + applyBlockSpendingScript(ErgoTree.fromProposition(SigmaAnd(defaultProver.hdKeys.map(s => SigmaPropConstant(s.publicImage))))) shouldBe 'success + applyBlockSpendingScript(ErgoTree.fromProposition(SigmaAnd(defaultMinerPk, ProveDlog(dlogGroup.generator)))) shouldBe 'failure + applyBlockSpendingScript(ErgoTree.fromProposition(SigmaOr(defaultMinerPk, ProveDlog(dlogGroup.generator)))) shouldBe 'success } property("predef scripts") { delta shouldBe -1000 - applyBlockSpendingScript(GE(Height, Plus(boxCreationHeight(Self), IntConstant(delta))).toSigmaProp) shouldBe 'success + applyBlockSpendingScript(ErgoTree.fromProposition(GE(Height, Plus(boxCreationHeight(Self), IntConstant(delta))).toSigmaProp)) shouldBe 'success applyBlockSpendingScript(ErgoTreePredef.rewardOutputScript(delta, defaultMinerPk)) shouldBe 'success // applyBlockSpendingScript(ErgoScriptPredef.feeProposition(delta)) shouldBe 'success } private def fromString(str: String): ErgoTree = { - compiler.compile(Map(), str).buildTree.asBoolValue.toSigmaProp + ErgoTree.fromProposition( + compiler.compile(Map(), str).buildTree.asBoolValue.toSigmaProp + ) } private def applyBlockSpendingScript(script: ErgoTree): Try[UtxoState] = { diff --git a/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala index e9db1e9e72..0563d63e96 100644 --- a/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala @@ -7,7 +7,7 @@ import org.ergoplatform.modifiers.mempool.ErgoTransaction import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} import org.ergoplatform.core._ import scorex.crypto.authds.ADDigest -import sigmastate.interpreter.ProverResult +import sigma.interpreter.ProverResult class DigestStateSpecification extends ErgoPropertyTest { diff --git a/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala index 4ce52bc67c..264b040b21 100644 --- a/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala @@ -20,9 +20,10 @@ import scorex.crypto.authds.ADKey import scorex.db.ByteArrayWrapper import scorex.util.{ModifierId, bytesToId} import scorex.util.encode.Base16 -import sigmastate.Values.ByteArrayConstant -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} -import sigmastate.interpreter.ProverResult +import sigma.ast.{ByteArrayConstant, ErgoTree} +import sigma.data.ProveDlog +import sigmastate.crypto.DLogProtocol.DLogProverInput +import sigma.interpreter.ProverResult import sigmastate.helpers.TestingHelpers._ import scala.concurrent.duration.Duration @@ -46,7 +47,7 @@ class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenera val inputs = IndexedSeq(Input(foundersBox.id, emptyProverResult)) val remaining = emission.remainingFoundationRewardAtHeight(height) val newFoundersBox = testBox(remaining, foundersBox.ergoTree, height, Seq(), Map(R4 -> foundersBox.additionalRegisters(R4))) - val rewardBox = testBox(foundersBox.value - remaining, defaultProver.hdKeys.last.publicImage, height) + val rewardBox = testBox(foundersBox.value - remaining, ErgoTree.fromSigmaBoolean(defaultProver.hdKeys.last.publicImage), height) val newBoxes = IndexedSeq(newFoundersBox, rewardBox) val unsignedTx = new UnsignedErgoTransaction(inputs, IndexedSeq(), newBoxes) val tx: ErgoTransaction = ErgoTransaction(defaultProver.sign(unsignedTx, IndexedSeq(foundersBox), emptyDataBoxes, us.stateContext).get) @@ -90,7 +91,7 @@ class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenera val inputs = IndexedSeq(Input(foundersBox.id, emptyProverResult)) val newBoxes = IndexedSeq( testBox(remaining, foundersBox.ergoTree, height, Seq(), foundersBox.additionalRegisters), - testBox(foundersBox.value - remaining, rewardPk, height, Seq()) + testBox(foundersBox.value - remaining, ErgoTree.fromSigmaBoolean(rewardPk), height, Seq()) ) val unsignedTx = new UnsignedErgoTransaction(inputs, IndexedSeq(), newBoxes) val tx = ErgoTransaction(defaultProver.sign(unsignedTx, IndexedSeq(foundersBox), emptyDataBoxes, us.stateContext).get) diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala index c492591ac0..d7991d2ef7 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala @@ -24,10 +24,9 @@ import org.scalacheck.Gen import org.scalatest.BeforeAndAfterAll import scorex.db.{LDBKVStore, LDBVersionedStore} import scorex.util.encode.Base16 -import sigmastate.Values.{ByteArrayConstant, EvaluatedValue} -import sigmastate.eval.Extensions.ArrayOps +import sigma.ast.{ByteArrayConstant, ErgoTree, EvaluatedValue, FalseLeaf, SType, TrueLeaf} +import sigma.Extensions.ArrayOps import sigmastate.helpers.TestingHelpers.testBox -import sigmastate.{SType, Values} import scala.collection.compat.immutable.ArraySeq import scala.util.Random @@ -92,7 +91,7 @@ class ErgoWalletServiceSpec ErgoLikeTransaction(IndexedSeq(), IndexedSeq()), creationOutIndex = 0, None, - testBox(1L, Values.TrueLeaf.toSigmaProp, 0), + testBox(1L, ErgoTree.fromProposition(TrueLeaf.toSigmaProp), 0), Set(PaymentsScanId) ) ) @@ -127,7 +126,7 @@ class ErgoWalletServiceSpec case (ergoBoxes, _) => val ergoBox = ergoBoxes.head - val registers: Option[Map[NonMandatoryRegisterId, EvaluatedValue[_ <: SType]]] = Option(Map(ErgoBox.R4 -> sigmastate.Values.FalseLeaf)) + val registers: Option[Map[NonMandatoryRegisterId, EvaluatedValue[_ <: SType]]] = Option(Map(ErgoBox.R4 -> FalseLeaf)) val illegalAssetIssueRequest = AssetIssueRequest(address = pks.head, Some(1), amount = 1, "test", "test", 4, registers) val invalidCandidates = requestsToBoxCandidates(Seq(illegalAssetIssueRequest), ergoBox.id, startHeight, parameters, pks) invalidCandidates.failed.get.getMessage shouldBe "Additional registers contain R0...R6" diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala index 73ef39d8ee..ffd225484b 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala @@ -17,10 +17,11 @@ import org.scalacheck.Gen import org.scalatest.concurrent.Eventually import scorex.util.ModifierId import scorex.util.encode.Base16 -import sigmastate.crypto.DLogProtocol.DLogProverInput +import sigma.ast.ErgoTree +import sigma.data.{CAND, CTHRESHOLD} import sigmastate.eval.Extensions._ -import sigmastate.eval._ -import sigmastate.{CAND, CTHRESHOLD} +import sigma.eval.Extensions.EvalIterableOps +import sigmastate.crypto.DLogProtocol.DLogProverInput import scala.concurrent.duration._ @@ -699,7 +700,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually // We need this second block to have something to rollback. Just spent some balance to anyone val balanceToSpend = randomLong(initialBalance) - val onchainSpendingTx = makeTx(initialBoxes, emptyProverResult, balanceToSpend, address.pubkey) + val onchainSpendingTx = makeTx(initialBoxes, emptyProverResult, balanceToSpend, ErgoTree.fromSigmaBoolean(address.pubkey)) val boxesToSpend = boxesAvailable(onchainSpendingTx, address.pubkey) val block = makeNextBlock(getUtxoState, Seq(onchainSpendingTx)) applyBlock(block) shouldBe 'success @@ -759,7 +760,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually eventually { val initialBalance = getConfirmedBalances.walletBalance val balanceToSpend = randomLong(balanceAmount(boxesToSpend)) - val creationTx = makeTx(boxesToSpend, emptyProverResult, balanceToSpend, pubKey, randomNewAsset) + val creationTx = makeTx(boxesToSpend, emptyProverResult, balanceToSpend, ErgoTree.fromSigmaBoolean(pubKey), randomNewAsset) val initialAssets = assetAmount(boxesAvailable(creationTx, pubKey)) initialAssets should not be empty log.info(s"Initial balance: $initialBalance") @@ -926,7 +927,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually val initialBalance = balanceAmount(initialBoxes) val balancePicked = randomLong(initialBalance) - val creationTx = makeTx(initialBoxes, emptyProverResult, balancePicked, address.pubkey, randomNewAsset) + val creationTx = makeTx(initialBoxes, emptyProverResult, balancePicked, ErgoTree.fromSigmaBoolean(address.pubkey), randomNewAsset) val boxesToSpend = boxesAvailable(creationTx, address.pubkey) val balanceToSpend = balanceAmount(boxesToSpend) @@ -1056,7 +1057,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually //pay out all the wallet balance: val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq assetToSpend should not be empty - val req1 = PaymentRequest(Pay2SAddress(CAND(Seq(secret1.publicImage, secret2.publicImage))), confirmedBalance, assetToSpend, Map.empty) + val req1 = PaymentRequest(Pay2SAddress(ErgoTree.fromSigmaBoolean(CAND(Seq(secret1.publicImage, secret2.publicImage)))), confirmedBalance, assetToSpend, Map.empty) val tx = await(wallet.generateTransaction(Seq(req1))).get @@ -1093,7 +1094,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually //pay out all the wallet balance: val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq assetToSpend should not be empty - val addr = Pay2SAddress(CTHRESHOLD(2, Seq(secret1.publicImage, secret2.publicImage, secret3.publicImage))) + val addr = Pay2SAddress(ErgoTree.fromSigmaBoolean(CTHRESHOLD(2, Seq(secret1.publicImage, secret2.publicImage, secret3.publicImage)))) val req1 = PaymentRequest(addr, confirmedBalance, assetToSpend, Map.empty) val tx = await(wallet.generateTransaction(Seq(req1))).get diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala index fb6d72e266..a8b2c1bfcb 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala @@ -1,16 +1,16 @@ package org.ergoplatform.nodeView.wallet -import org.ergoplatform.utils.{ErgoPropertyTest, WalletTestOps} -import WalletScanLogic.{extractWalletOutputs, scanBlockTransactions} import org.ergoplatform.db.DBSpec -import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input} import org.ergoplatform.modifiers.mempool.ErgoTransaction +import org.ergoplatform.nodeView.wallet.WalletScanLogic.{extractWalletOutputs, scanBlockTransactions} import org.ergoplatform.nodeView.wallet.persistence.{OffChainRegistry, WalletRegistry} import org.ergoplatform.nodeView.wallet.scanning.{EqualsScanningPredicate, ScanRequest, ScanWalletInteraction} +import org.ergoplatform.utils.{ErgoPropertyTest, WalletTestOps} import org.ergoplatform.wallet.Constants import org.ergoplatform.wallet.Constants.ScanId +import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input} import org.scalacheck.Gen -import sigmastate.Values.{ByteArrayConstant, ErgoTree, FalseLeaf, TrueLeaf} +import sigma.ast.{ByteArrayConstant, ErgoTree, FalseLeaf, TrueLeaf} import scala.util.Random @@ -40,11 +40,11 @@ class WalletScanLogicSpec extends ErgoPropertyTest with DBSpec with WalletTestOp private val pubkeys = prover.hdPubKeys private val miningScripts = WalletCache.miningScripts(pubkeys, s) - private def paymentsGen: Gen[List[ErgoTree]] = Gen.listOf(Gen.oneOf(pubkeys.map(_.key.toSigmaProp: ErgoTree))) + private def paymentsGen: Gen[List[ErgoTree]] = Gen.listOf(Gen.oneOf(pubkeys.map(epk => ErgoTree.fromSigmaBoolean(epk.key)))) private def miningRewardsGen: Gen[List[ErgoTree]] = Gen.listOf(Gen.oneOf(miningScripts)) - private def nonTrackablePaymentsGen: Gen[List[ErgoTree]] = Gen.nonEmptyListOf(Gen.const(FalseLeaf.toSigmaProp)) + private def nonTrackablePaymentsGen: Gen[List[ErgoTree]] = Gen.nonEmptyListOf(Gen.const(ErgoTree.fromProposition(FalseLeaf.toSigmaProp))) private def appPaymentsGen: Gen[List[ErgoTree]] = Gen.listOf(Gen.const(trueProp)) @@ -192,7 +192,13 @@ class WalletScanLogicSpec extends ErgoPropertyTest with DBSpec with WalletTestOp //applying a transaction spending outputs of the previous transaction val inputs2 = spendingTx.outputs.map(_.id).map(id => Input(id, emptyProverResult)) - val outputs2 = IndexedSeq(new ErgoBoxCandidate(spendingTx.outputs.map(_.value).sum, FalseLeaf.toSigmaProp, height1)) + val outputs2 = IndexedSeq( + new ErgoBoxCandidate( + spendingTx.outputs.map(_.value).sum, + ErgoTree.fromProposition(FalseLeaf.toSigmaProp), + height1 + ) + ) val spendingTx2 = new ErgoTransaction(inputs2, IndexedSeq.empty, outputs2) val (r3, o3, f3) = @@ -239,7 +245,7 @@ class WalletScanLogicSpec extends ErgoPropertyTest with DBSpec with WalletTestOp property("external scan prioritized over payments one if walletInteraction = off, otherwise shared") { val intFlagGen = Gen.oneOf(ScanWalletInteraction.Off, ScanWalletInteraction.Shared, ScanWalletInteraction.Forced) forAll(intFlagGen) { intFlag => - val pk = pubkeys.head.key.toSigmaProp: ErgoTree + val pk = ErgoTree.fromSigmaBoolean(pubkeys.head.key) val outs = IndexedSeq(new ErgoBoxCandidate(1000, pk, creationHeight = 1)) val tx = new ErgoTransaction(fakeInputs, IndexedSeq.empty, outs) @@ -263,7 +269,7 @@ class WalletScanLogicSpec extends ErgoPropertyTest with DBSpec with WalletTestOp } property("scan with forced flag is sharing boxes with the p2k-wallet") { - val trueProp = TrueLeaf.toSigmaProp.treeWithSegregation: ErgoTree + val trueProp = ErgoTree.fromProposition(TrueLeaf.toSigmaProp) val outs = IndexedSeq(new ErgoBoxCandidate(1000, trueProp, creationHeight = 1)) val tx = new ErgoTransaction(fakeInputs, IndexedSeq.empty, outs) diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistrySpec.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistrySpec.scala index 886fbf38ce..335e2f22ff 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistrySpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistrySpec.scala @@ -10,7 +10,7 @@ import org.scalacheck.Gen import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigmastate.Values.ByteArrayConstant +import sigma.ast.ByteArrayConstant import scala.collection.immutable.TreeSet import scala.util.Random diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistryBenchmark.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistryBenchmark.scala index 1dad6a9df8..fd05cf49be 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistryBenchmark.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistryBenchmark.scala @@ -12,8 +12,9 @@ import org.ergoplatform.wallet.interpreter.ErgoProvingInterpreter import org.ergoplatform.{ErgoAddressEncoder, ErgoBox, Input} import scorex.util.ModifierId import scorex.util.encode.Base16 -import sigmastate.Values.ErgoTree -import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigma.Colls +import sigma.ast.ErgoTree +import sigma.interpreter.{ContextExtension, ProverResult} import scala.collection.compat.immutable.ArraySeq @@ -26,9 +27,8 @@ object WalletRegistryBenchmark extends App with ErgoTestConstants { additionalRegisters: AdditionalRegisters = Map.empty, transactionId: ModifierId = ErgoBox.allZerosModifierId, boxIndex: Short = 0): ErgoBox = { - import sigmastate.eval._ new ErgoBox(value, ergoTree, - CostingSigmaDslBuilder.Colls.fromArray(additionalTokens.toArray[(TokenId, Long)]), + Colls.fromArray(additionalTokens.toArray[(TokenId, Long)]), additionalRegisters, transactionId, boxIndex, creationHeight) } @@ -50,7 +50,7 @@ object WalletRegistryBenchmark extends App with ErgoTestConstants { val walletVars = WalletVars.apply(storage, settings).withProver(prover) val boxes = walletVars.proverOpt.get.hdPubKeys.map { pk => - createBox(1000000000, pk.key, 1) + createBox(1000000000, ErgoTree.fromSigmaBoolean(pk.key), 1) }.map { box => TrackedBox(box, 2, Set(Constants.PaymentsScanId)) } diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecsSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecsSpecification.scala index 4d015ac027..172673c42a 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecsSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecsSpecification.scala @@ -5,7 +5,7 @@ import org.ergoplatform.ErgoBox import org.ergoplatform.utils.ErgoPropertyTest import org.ergoplatform.utils.generators.WalletGenerators import scorex.util.encode.Base16 -import sigmastate.Values.ByteArrayConstant +import sigma.ast.ByteArrayConstant import sigmastate.eval.Extensions.ArrayByteOps import scala.language.implicitConversions diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSpecification.scala index dcfc049dbe..dd0ede4458 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSpecification.scala @@ -6,7 +6,7 @@ import org.ergoplatform.utils.ErgoPropertyTest import org.ergoplatform.utils.generators.ErgoTransactionGenerators import org.ergoplatform.wallet.serialization.JsonCodecsWrapper import org.ergoplatform.{ErgoTreePredef, P2PKAddress} -import sigmastate.Values.ByteArrayConstant +import sigma.ast.{ByteArrayConstant, ErgoTree} import sigmastate.eval.Extensions.ArrayByteOps import sigmastate.helpers.TestingHelpers._ @@ -95,10 +95,10 @@ class ScanningPredicateSpecification extends ErgoPropertyTest with ErgoTransacti property("containsAsset") { forAll(proveDlogGen) { pk => forAll(assetGen) { case (tokenId, amt) => - val box = testBox(value = 1, pk, creationHeight = 0, additionalTokens = Seq(tokenId -> amt)) + val box = testBox(value = 1, ErgoTree.fromSigmaBoolean(pk), creationHeight = 0, additionalTokens = Seq(tokenId -> amt)) ContainsAssetPredicate(tokenId).filter(box) shouldBe true - val emptyBox = testBox(value = 1, pk, creationHeight = 0) + val emptyBox = testBox(value = 1, ErgoTree.fromSigmaBoolean(pk), creationHeight = 0) ContainsAssetPredicate(tokenId).filter(emptyBox) shouldBe false ContainsAssetPredicate(mutateRandomByte(tokenId.toArray).toTokenId).filter(box) shouldBe false diff --git a/src/test/scala/org/ergoplatform/reemission/ReemissionRulesSpec.scala b/src/test/scala/org/ergoplatform/reemission/ReemissionRulesSpec.scala index 46a670cab6..483d3988b9 100644 --- a/src/test/scala/org/ergoplatform/reemission/ReemissionRulesSpec.scala +++ b/src/test/scala/org/ergoplatform/reemission/ReemissionRulesSpec.scala @@ -6,9 +6,9 @@ import org.ergoplatform.utils.{ErgoPropertyTest, ErgoTestConstants} import scorex.crypto.hash.Blake2b256 import scorex.util.ModifierId import sigma.Colls -import sigmastate.AvlTreeData -import sigmastate.TrivialProp.TrueProp -import sigmastate.eval.Digest32Coll +import sigma.ast.ErgoTree +import sigma.data.TrivialProp.TrueProp +import sigma.data.{AvlTreeData, Digest32Coll} import sigmastate.helpers.TestingHelpers.testBox import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} import sigmastate.interpreter.Interpreter.emptyEnv @@ -151,7 +151,7 @@ class ReemissionRulesSpec extends ErgoPropertyTest with ErgoTestConstants { // merging with 1 box - successful case val newReemissionBox = new ErgoBoxCandidate(reemissionBox.value + mergedValue - feeValue, prop, currentHeight, reemissionBoxAssets) - val feeBox = new ErgoBoxCandidate(feeValue, TrueProp, currentHeight) + val feeBox = new ErgoBoxCandidate(feeValue, ErgoTree.fromSigmaBoolean(TrueProp), currentHeight) val spendingTransaction = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox, feeBox)) checkRewardsTx(currentHeight, pkBytes, inputBoxes, spendingTransaction, true) @@ -166,7 +166,7 @@ class ReemissionRulesSpec extends ErgoPropertyTest with ErgoTestConstants { // paying too high fee val newReemissionBox3 = new ErgoBoxCandidate(reemissionBox.value + mergedValue - feeValue - 1, prop, currentHeight, reemissionBoxAssets) - val feeBox3 = new ErgoBoxCandidate(feeValue + 1, TrueProp, currentHeight) + val feeBox3 = new ErgoBoxCandidate(feeValue + 1, ErgoTree.fromSigmaBoolean(TrueProp), currentHeight) val spendingTransaction3 = ErgoLikeTransaction(inputs2, IndexedSeq(newReemissionBox3, feeBox3)) checkRewardsTx(currentHeight, pkBytes, inputBoxes, spendingTransaction3, false) @@ -180,7 +180,7 @@ class ReemissionRulesSpec extends ErgoPropertyTest with ErgoTestConstants { // reemission box value must be increased val feeValue5 = mergedValue val newReemissionBox5 = new ErgoBoxCandidate(reemissionBox.value + mergedValue - feeValue5, prop, currentHeight, reemissionBoxAssets) - val feeBox5 = new ErgoBoxCandidate(feeValue5, TrueProp, currentHeight) + val feeBox5 = new ErgoBoxCandidate(feeValue5, ErgoTree.fromSigmaBoolean(TrueProp), currentHeight) val spendingTransaction5 = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox5, feeBox5)) checkRewardsTx(currentHeight, pkBytes, inputBoxes, spendingTransaction5, false) diff --git a/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala b/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala index 09ff24da54..48501fcb3f 100644 --- a/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala +++ b/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala @@ -18,8 +18,7 @@ import org.ergoplatform.utils.generators.WalletGenerators import org.ergoplatform.wallet.Constants.ScanId import org.ergoplatform.wallet.boxes.TrackedBox import org.scalatest.Inspectors -import sigmastate.SType -import sigmastate.Values.{ErgoTree, EvaluatedValue} +import sigma.ast.{ErgoTree, EvaluatedValue, SType} import scala.util.Random diff --git a/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala b/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala index 1d444969e5..60b260a4bd 100644 --- a/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala +++ b/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala @@ -5,8 +5,9 @@ import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.nodeView.state.{ErgoStateContext, VotingData} import org.ergoplatform.settings.ValidationRules.rulesSpec import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.validation.{DisabledRule, ReplacedRule, ValidationRules => VR} +import org.ergoplatform.validation.{ValidationRules => VR} import scorex.crypto.authds.ADDigest +import sigma.validation.{DisabledRule, ReplacedRule} import scala.util.Try @@ -35,7 +36,7 @@ class VotingSpecification extends ErgoPropertyTest { private val proposedUpdate = ErgoValidationSettingsUpdate( Seq(ValidationRules.exDuplicateKeys, ValidationRules.exValueLength), - Seq(VR.CheckDeserializedScriptType.id -> DisabledRule, VR.CheckValidOpCode.id -> ReplacedRule((VR.FirstRuleId + 11).toShort))) + Seq(VR.CheckDeserializedScriptType.id -> DisabledRule, VR.CheckValidOpCode.id -> ReplacedRule((sigma.validation.ValidationRules.FirstRuleId + 11).toShort))) private val proposedUpdate2 = ErgoValidationSettingsUpdate(Seq(ValidationRules.fbOperationFailed), Seq()) val ctx: ErgoStateContext = { new ErgoStateContext(Seq.empty, None, genesisStateDigest, parameters, validationSettingsNoIl, VotingData.empty)(updSettings.chainSettings) @@ -50,7 +51,7 @@ class VotingSpecification extends ErgoPropertyTest { property("correct rule ids") { rulesSpec foreach { r => - r._1 < org.ergoplatform.validation.ValidationRules.FirstRuleId shouldBe true + r._1 < sigma.validation.ValidationRules.FirstRuleId shouldBe true } } diff --git a/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala b/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala index a74c1f1a67..eb470d4ecf 100644 --- a/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala +++ b/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala @@ -16,7 +16,7 @@ import org.ergoplatform.settings._ import org.ergoplatform.utils.{ErgoTestHelpers, HistoryTestHelpers} import org.ergoplatform.wallet.boxes.{BoxSelector, ReplaceCompactCollectBoxSelector} import scorex.util.ModifierId -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.data.ProveDlog import java.io.File import scala.annotation.tailrec diff --git a/src/test/scala/org/ergoplatform/tools/FeeSimulator.scala b/src/test/scala/org/ergoplatform/tools/FeeSimulator.scala index 9eebe3f4b7..218c6f4753 100644 --- a/src/test/scala/org/ergoplatform/tools/FeeSimulator.scala +++ b/src/test/scala/org/ergoplatform/tools/FeeSimulator.scala @@ -7,10 +7,10 @@ import org.ergoplatform.{ErgoBoxCandidate, Input} import scorex.crypto.authds.ADKey import scorex.utils.Random import sigma.Colls +import sigma.ast.ErgoTree import sigmastate.crypto.DLogProtocol.DLogProverInput import sigmastate.eval.Extensions.ArrayByteOps -import sigmastate.eval._ -import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigma.interpreter.{ContextExtension, ProverResult} object FeeSimulator extends App { @@ -25,9 +25,9 @@ object FeeSimulator extends App { val creationHeight: Int = 100000 val box1 = new ErgoBoxCandidate( - scala.util.Random.nextLong(), k1, creationHeight, + scala.util.Random.nextLong(), ErgoTree.fromSigmaBoolean(k1), creationHeight, Colls.fromItems(Random.randomBytes(32).toTokenId -> scala.util.Random.nextLong())) - val box2 = new ErgoBoxCandidate(scala.util.Random.nextLong(), k2, creationHeight) + val box2 = new ErgoBoxCandidate(scala.util.Random.nextLong(), ErgoTree.fromSigmaBoolean(k2), creationHeight) val simpleTx = ErgoTransaction(IndexedSeq(input, input), IndexedSeq(box1, box2)) val stdSize = simpleTx.outputs.map(_.bytes.length).sum / simpleTx.outputs.length diff --git a/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala b/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala index 4cd5bc4311..a9ca4fbf14 100644 --- a/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala +++ b/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala @@ -20,10 +20,11 @@ import org.ergoplatform.{DataInput, ErgoBox, ErgoTreePredef} import scorex.crypto.authds.ADDigest import scorex.crypto.hash.Digest32 import scorex.util.ScorexLogging -import sigmastate.Values.ErgoTree -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} -import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigma.ast.ErgoTree +import sigma.crypto.EcPointType +import sigma.data.ProveDlog +import sigma.interpreter.{ContextExtension, ProverResult} +import sigmastate.crypto.DLogProtocol.DLogProverInput import scala.concurrent.duration._ diff --git a/src/test/scala/org/ergoplatform/utils/Stubs.scala b/src/test/scala/org/ergoplatform/utils/Stubs.scala index 53186f5a77..b8121a03dd 100644 --- a/src/test/scala/org/ergoplatform/utils/Stubs.scala +++ b/src/test/scala/org/ergoplatform/utils/Stubs.scala @@ -9,6 +9,7 @@ import org.ergoplatform.mining.{AutolykosSolution, CandidateGenerator, ErgoMiner import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} +import org.ergoplatform.network.peer.PeerManager.ReceivableMessages.{GetAllPeers, GetBlacklistedPeers} import org.ergoplatform.network.{Handshake, PeerSpec, Version} import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedTransaction import org.ergoplatform.nodeView.ErgoReadersHolder.{GetDataFromHistory, GetReaders, Readers} @@ -25,7 +26,7 @@ import org.ergoplatform.nodeView.wallet.scanning.Scan import org.ergoplatform.sanity.ErgoSanity.HT import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey} import org.ergoplatform.settings.Constants.HashLength -import org.ergoplatform.settings.{ScorexSettings, _} +import org.ergoplatform.settings._ import org.ergoplatform.utils.generators.{ChainGenerator, ErgoGenerators, ErgoTransactionGenerators} import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId} import org.ergoplatform.wallet.boxes.{ChainStatus, TrackedBox} @@ -35,13 +36,12 @@ import org.ergoplatform.wallet.mnemonic.Mnemonic import org.ergoplatform.wallet.utils.TestFileUtils import org.scalacheck.Gen import scorex.core.network.NetworkController.ReceivableMessages.GetConnectedPeers -import org.ergoplatform.network.peer.PeerManager.ReceivableMessages.{GetAllPeers, GetBlacklistedPeers} -import org.ergoplatform.network.PeerSpec import scorex.crypto.authds.ADDigest import scorex.crypto.hash.Digest32 import scorex.db.ByteArrayWrapper import scorex.util.Random -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} +import sigma.data.ProveDlog +import sigmastate.crypto.DLogProtocol.DLogProverInput import scala.collection.mutable import scala.concurrent.duration._ diff --git a/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala b/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala index f88e087f4a..0d794acbb3 100644 --- a/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala +++ b/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala @@ -17,12 +17,12 @@ import scorex.crypto.authds.ADKey import scorex.crypto.hash.Blake2b256 import scorex.util.ModifierId import sigma.Colls -import sigmastate.Values.ErgoTree -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.ast.ErgoTree +import sigma.data.ProveDlog import sigmastate.eval.Extensions._ -import sigmastate.eval._ -import sigmastate.interpreter.ProverResult +import sigma.interpreter.ProverResult import sigma.Extensions._ +import sigma.eval.Extensions.EvalIterableOps trait WalletTestOps extends NodeViewBaseOps { diff --git a/src/test/scala/org/ergoplatform/utils/generators/ChainGenerator.scala b/src/test/scala/org/ergoplatform/utils/generators/ChainGenerator.scala index cfe35ca205..16866af772 100644 --- a/src/test/scala/org/ergoplatform/utils/generators/ChainGenerator.scala +++ b/src/test/scala/org/ergoplatform/utils/generators/ChainGenerator.scala @@ -14,9 +14,8 @@ import org.ergoplatform.utils.{BoxUtils, ErgoTestConstants} import scorex.crypto.authds.{ADKey, SerializedAdProof} import scorex.crypto.hash.Digest32 import sigma.Colls -import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ -import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigma.interpreter.{ContextExtension, ProverResult} import scala.util.Random diff --git a/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala b/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala index 311ce9d00b..83447f2aa1 100644 --- a/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala +++ b/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala @@ -15,18 +15,19 @@ import org.ergoplatform.nodeView.state.StateType import org.ergoplatform.settings.{Constants, ErgoValidationSettings, ErgoValidationSettingsUpdate, ValidationRules} import org.ergoplatform.testkit.generators.CoreGenerators import org.ergoplatform.utils.ErgoTestConstants -import org.ergoplatform.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule} +import sigma.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule} import org.ergoplatform.wallet.utils.Generators import org.scalacheck.Arbitrary.arbByte import org.scalacheck.{Arbitrary, Gen} import org.scalatest.matchers.should.Matchers import scorex.crypto.authds.{ADDigest, SerializedAdProof} import scorex.crypto.hash.Digest32 -import sigmastate.Values.ErgoTree -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} -import sigmastate.crypto.{CryptoConstants, DiffieHellmanTupleProverInput, ProveDHTuple} -import sigmastate.interpreter.ProverResult +import sigma.ast.ErgoTree +import sigma.crypto.{CryptoConstants, EcPointType} +import sigma.data.{ProveDHTuple, ProveDlog} +import sigmastate.crypto.DLogProtocol.DLogProverInput +import sigmastate.crypto.DiffieHellmanTupleProverInput +import sigma.interpreter.ProverResult import scala.util.Random @@ -58,7 +59,7 @@ trait ErgoGenerators extends CoreGenerators with ChainGenerator with Generators seed <- genBytes(32) } yield DLogProverInput(BigIntegers.fromUnsignedByteArray(seed)).publicImage - lazy val proveDlogTreeGen: Gen[ErgoTree] = proveDlogGen.map(_.toSigmaProp) + lazy val proveDlogTreeGen: Gen[ErgoTree] = proveDlogGen.map(dl => ErgoTree.fromSigmaBoolean(dl)) lazy val ergoPropositionGen: Gen[ErgoTree] = Gen.oneOf(trueLeafGen, falseLeafGen, proveDlogTreeGen) @@ -181,7 +182,7 @@ trait ErgoGenerators extends CoreGenerators with ChainGenerator with Generators lazy val ergoValidationSettingsUpdateGen: Gen[ErgoValidationSettingsUpdate] = for { n <- Gen.choose(1, 200) disabledRules = ValidationRules.rulesSpec.filter(_._2.mayBeDisabled).keys.take(n).toSeq - replacedRuleCode <- Gen.choose(org.ergoplatform.validation.ValidationRules.FirstRuleId, Short.MaxValue) + replacedRuleCode <- Gen.choose(sigma.validation.ValidationRules.FirstRuleId, Short.MaxValue) changedRuleValue <- genBoundedBytes(0, 127) statuses <- Gen.listOf(Gen.oneOf(DisabledRule, EnabledRule, ReplacedRule(replacedRuleCode), ChangedRule(changedRuleValue))) statusUpdates = org.ergoplatform.validation.ValidationRules.ruleSpecs.take(statuses.size).map(_.id).zip(statuses) diff --git a/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala b/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala index e80b368edb..936a3860ad 100644 --- a/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala +++ b/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala @@ -23,11 +23,11 @@ import org.scalacheck.Gen import scorex.crypto.hash.Blake2b256 import scorex.db.ByteArrayWrapper import scorex.util.encode.Base16 -import sigmastate.Values.ErgoTree -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.ast.ErgoTree +import sigma.data.ProveDlog import sigmastate.eval.Extensions._ -import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ +import sigma.eval.Extensions.EvalIterableOps import scala.collection.JavaConverters._ import scala.collection.mutable @@ -55,7 +55,7 @@ trait ErgoTransactionGenerators extends ErgoGenerators with Generators { ar <- additionalRegistersGen tokens <- additionalTokensGen value <- validValueGen - } yield new ErgoBoxCandidate(value, prop, h, tokens.toColl, ar) + } yield new ErgoBoxCandidate(value, ErgoTree.fromSigmaBoolean(prop), h, tokens.toColl, ar) lazy val ergoBoxGenNoProp: Gen[ErgoBox] = ergoBoxGen(propGen = trueLeafGen) @@ -337,7 +337,7 @@ trait ErgoTransactionGenerators extends ErgoGenerators with Generators { def transactionSigningRequestGen(includeInputs: Boolean): Gen[TransactionSigningRequest] = for { (secret, pubKey) <- dlogSecretWithPublicImageGen (secretDh, _) <- dhtSecretWithPublicImageGen - (inputBoxes, utx) <- validUnsignedErgoTransactionGen(pubKey) + (inputBoxes, utx) <- validUnsignedErgoTransactionGen(ErgoTree.fromSigmaBoolean(pubKey)) inputBoxesEncoded = inputBoxes.map(b => Base16.encode(b.bytes)) secretSeq = Seq(ExternalSecret(DlogSecretKey(secret)), ExternalSecret(DhtSecretKey(secretDh))) } yield TransactionSigningRequest(utx, TransactionHintsBag.empty, secretSeq, diff --git a/src/test/scala/org/ergoplatform/utils/generators/WalletGenerators.scala b/src/test/scala/org/ergoplatform/utils/generators/WalletGenerators.scala index 5ec1522c19..e0fb16ff1c 100644 --- a/src/test/scala/org/ergoplatform/utils/generators/WalletGenerators.scala +++ b/src/test/scala/org/ergoplatform/utils/generators/WalletGenerators.scala @@ -11,7 +11,7 @@ import org.ergoplatform.wallet.Constants.ScanId import org.ergoplatform.wallet.boxes.TrackedBox import org.ergoplatform.wallet.utils.Generators import org.scalacheck.Gen -import sigmastate.Values.ByteArrayConstant +import sigma.ast.ByteArrayConstant trait WalletGenerators extends ErgoTransactionGenerators with Generators { From 5e9d8d047763159967b9c8d8e141a46013218a8e Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 29 Mar 2024 18:08:35 +0300 Subject: [PATCH 02/36] 5.0.22 version set, checkpoint updated to 1,231,454 --- src/main/resources/api/openapi-ai.yaml | 2 +- src/main/resources/api/openapi.yaml | 2 +- src/main/resources/application.conf | 2 +- src/main/resources/mainnet.conf | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/resources/api/openapi-ai.yaml b/src/main/resources/api/openapi-ai.yaml index f6cbea204d..1cadbe01e6 100644 --- a/src/main/resources/api/openapi-ai.yaml +++ b/src/main/resources/api/openapi-ai.yaml @@ -1,7 +1,7 @@ openapi: "3.0.2" info: - version: "5.0.21" + version: "5.0.22" title: Ergo Node API description: Specification of Ergo Node API for ChatGPT plugin. The following endpoints supported diff --git a/src/main/resources/api/openapi.yaml b/src/main/resources/api/openapi.yaml index a49f06f81c..d77c0d0f5f 100644 --- a/src/main/resources/api/openapi.yaml +++ b/src/main/resources/api/openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.2" info: - version: "5.0.21" + version: "5.0.22" title: Ergo Node API description: API docs for Ergo Node. Models are shared between all Ergo products contact: diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 7d30c0ea97..37c2406a53 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -436,7 +436,7 @@ scorex { nodeName = "ergo-node" # Network protocol version to be sent in handshakes - appVersion = 5.0.21 + appVersion = 5.0.22 # Network agent name. May contain information about client code # stack, starting from core code-base up to the end graphical interface. diff --git a/src/main/resources/mainnet.conf b/src/main/resources/mainnet.conf index 594044789e..dfc6850e84 100644 --- a/src/main/resources/mainnet.conf +++ b/src/main/resources/mainnet.conf @@ -70,8 +70,8 @@ ergo { # # To validate all the scripts for all the blocks, set checkpoint = null. checkpoint = { - height = 1020454 - blockId = "7829c6513c5b319b86e87253ed29d51fed61597c65e32f5197434461ccc4c905" + height = 1231454 + blockId = "ca5aa96a2d560f49cd5652eae4b9e16bbf410ee32365313dc16544ee5fda1e6d" } # List with hex-encoded identifiers of transactions banned from getting into memory pool From 9b17889443eace153b6403b5e819dc38b67a80e3 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 4 Apr 2024 13:45:12 +0300 Subject: [PATCH 03/36] removing hasLength which is always true --- .../difficulty/DifficultySerializer.scala | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala index a4aefe426d..9e587e9ed6 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala @@ -40,7 +40,7 @@ object DifficultySerializer extends ErgoSerializer[NBits] { if (size >= 1) bytes(4) = ((compact >> 16) & 0xFF).toByte if (size >= 2) bytes(5) = ((compact >> 8) & 0xFF).toByte if (size >= 3) bytes(6) = (compact & 0xFF).toByte - decodeMPI(bytes, hasLength = true) + decodeMPI(bytes) } /** @@ -78,19 +78,15 @@ object DifficultySerializer extends ErgoSerializer[NBits] { * MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of * a 4 byte big endian length field, followed by the stated number of bytes representing * the number in big endian format (with a sign bit). - * - * @param hasLength can be set to false if the given array is missing the 4 byte length field */ @SuppressWarnings(Array("NullAssignment")) - private def decodeMPI(mpi: Array[Byte], hasLength: Boolean): BigInteger = { + private def decodeMPI(mpi: Array[Byte]): BigInteger = { var buf: Array[Byte] = null // scalastyle:ignore - if (hasLength) { - val length: Int = readUint32BE(mpi).toInt - buf = new Array[Byte](length) - System.arraycopy(mpi, 4, buf, 0, length) - } else { - buf = mpi - } + + val length: Int = readUint32BE(mpi).toInt + buf = new Array[Byte](length) + System.arraycopy(mpi, 4, buf, 0, length) + if (buf.length == 0) { BigInteger.ZERO } else { From 461c7b3ac55f90183d56a558468ecfb9a688651a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 4 Apr 2024 13:46:15 +0300 Subject: [PATCH 04/36] var buf = null eliminated --- .../ergoplatform/mining/difficulty/DifficultySerializer.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala index 9e587e9ed6..3c42fc6303 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala @@ -79,12 +79,10 @@ object DifficultySerializer extends ErgoSerializer[NBits] { * a 4 byte big endian length field, followed by the stated number of bytes representing * the number in big endian format (with a sign bit). */ - @SuppressWarnings(Array("NullAssignment")) private def decodeMPI(mpi: Array[Byte]): BigInteger = { - var buf: Array[Byte] = null // scalastyle:ignore val length: Int = readUint32BE(mpi).toInt - buf = new Array[Byte](length) + val buf = new Array[Byte](length) System.arraycopy(mpi, 4, buf, 0, length) if (buf.length == 0) { From aed60a0252c7852c84deba42d8a7c13297a26a9a Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 5 Apr 2024 20:28:57 +0100 Subject: [PATCH 05/36] sigma-5.0.14: update sigma to v5.0.14 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 7b35d07c6f..e758f23240 100644 --- a/build.sbt +++ b/build.sbt @@ -37,7 +37,7 @@ val circeVersion = "0.13.0" val akkaVersion = "2.6.10" val akkaHttpVersion = "10.2.4" -val sigmaStateVersion = "5.0.13-181-c2d4cc97-SNAPSHOT" +val sigmaStateVersion = "5.0.14" val ficusVersion = "1.4.7" // for testing current sigmastate build (see sigmastate-ergo-it jenkins job) From 1b91745c3ff68644a765e590f9f8822e747d87ad Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 10 Apr 2024 17:55:14 +0100 Subject: [PATCH 06/36] sigma-5.0.14: fixes after merge: compilation --- .../modifiers/mempool/ErgoTransactionSpec.scala | 16 ++++++++-------- .../JsonSerializationCoreSpec.scala | 3 +-- .../settings/VotingSpecification.scala | 3 +-- .../utils/generators/ErgoCoreGenerators.scala | 3 --- .../ErgoCoreTransactionGenerators.scala | 8 ++++---- .../wallet/utils/WalletGenerators.scala | 6 ++---- .../scala/org/ergoplatform/it/WalletSpec.scala | 1 - 7 files changed, 16 insertions(+), 24 deletions(-) diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala index 003e2b0372..ccab5036c8 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala @@ -9,12 +9,12 @@ import scorex.crypto.authds.ADKey import scorex.util.encode.Base16 import scorex.util.ModifierId import sigma.Colls -import sigmastate.Values.{ByteArrayConstant, ByteConstant, IntConstant, LongArrayConstant, SigmaPropConstant} -import sigmastate.crypto.CryptoConstants -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.eval._ -import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigma.eval._ import cats.syntax.either._ +import sigma.ast.{ByteArrayConstant, ByteConstant, ErgoTree, IntConstant, LongArrayConstant, SigmaPropConstant} +import sigma.crypto.CryptoConstants +import sigma.data.ProveDlog +import sigma.interpreter.{ContextExtension, ProverResult} import sigmastate.utils.Helpers._ @@ -48,7 +48,7 @@ class ErgoTransactionSpec extends ErgoCorePropertyTest { new ProverResult(Base16.decode("5aea4d78a234c35accacdf8996b0af5b51e26fee29ea5c05468f23707d31c0df39400127391cd57a70eb856710db48bb9833606e0bf90340").get, ContextExtension.empty))) val outputCandidates: IndexedSeq[ErgoBoxCandidate] = IndexedSeq( - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, Map()), + new ErgoBoxCandidate(1000000000L, ErgoTree.fromSigmaBoolean(minerPk), height, Colls.emptyColl, Map()), new ErgoBoxCandidate(1000000L, chainSettings.monetary.feeProposition, height, Colls.emptyColl, Map()) ) val tx = ErgoTransaction(inputs: IndexedSeq[Input], outputCandidates: IndexedSeq[ErgoBoxCandidate]) @@ -62,7 +62,7 @@ class ErgoTransactionSpec extends ErgoCorePropertyTest { // tx with registers in outputs val outputCandidates2: IndexedSeq[ErgoBoxCandidate] = IndexedSeq( - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, + new ErgoBoxCandidate(1000000000L, ErgoTree.fromSigmaBoolean(minerPk), height, Colls.emptyColl, Map( R6 -> IntConstant(10), R4 -> ByteConstant(1), @@ -70,7 +70,7 @@ class ErgoTransactionSpec extends ErgoCorePropertyTest { R7 -> LongArrayConstant(Array(1L, 2L, 1234123L)), R8 -> ByteArrayConstant(Base16.decode("123456123456123456123456123456123456123456123456123456123456123456").get)) ), - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, Map())) + new ErgoBoxCandidate(1000000000L, ErgoTree.fromSigmaBoolean(minerPk), height, Colls.emptyColl, Map())) val tx2 = ErgoTransaction(inputs: IndexedSeq[Input], outputCandidates2: IndexedSeq[ErgoBoxCandidate]) Base16.encode(tx2.bytes) shouldBe "02c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f774238b4a04b4201da0578be3dac11067b567a73831f35b024a2e623c1f8da230407f63bab62c62ed9b93808b106b5a7e8b1751fa656f4c5de467400ca796a4fc9c0d746a69702a77bd78b1a80a5ef5bf5713bbd95d93a4f23b27ead385aea4d78a234c35accacdf8996b0af5b51e26fee29ea5c05468f23707d31c0df39400127391cd57a70eb856710db48bb9833606e0bf90340000000028094ebdc030008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942e8070005020108cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b94204141103020496d396010e211234561234561234561234561234561234561234561234561234561234561234568094ebdc030008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942e8070000" diff --git a/ergo-core/src/test/scala/org/ergoplatform/serialization/JsonSerializationCoreSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/serialization/JsonSerializationCoreSpec.scala index 7a765c0fd0..360cb1c52e 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/serialization/JsonSerializationCoreSpec.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/serialization/JsonSerializationCoreSpec.scala @@ -12,9 +12,8 @@ import org.ergoplatform.settings.Algos import org.ergoplatform.utils.ErgoCorePropertyTest import org.ergoplatform.wallet.Constants.ScanId import org.ergoplatform.wallet.boxes.TrackedBox -import sigmastate.SType -import sigmastate.Values.{ErgoTree, EvaluatedValue} import cats.syntax.either._ +import sigma.ast.{ErgoTree, EvaluatedValue, SType} class JsonSerializationCoreSpec extends ErgoCorePropertyTest with ApiCodecs { diff --git a/ergo-core/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala index 262acd5dcb..fd8de4dd5b 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala @@ -4,10 +4,9 @@ import org.ergoplatform.modifiers.history.extension.ExtensionCandidate import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.nodeView.state.{ErgoStateContext, VotingData} import org.ergoplatform.settings.ValidationRules.rulesSpec -import org.ergoplatform.utils.ErgoPropertyTest import org.ergoplatform.validation.{ValidationRules => VR} import org.ergoplatform.utils.ErgoCorePropertyTest -import org.ergoplatform.validation.{DisabledRule, ReplacedRule, ValidationRules => VR} +import org.ergoplatform.validation.{ValidationRules => VR} import scorex.crypto.authds.ADDigest import sigma.validation.{DisabledRule, ReplacedRule} import sigmastate.utils.Helpers._ diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala index 6a42a3e21a..378b8cd9f7 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala @@ -11,10 +11,7 @@ import org.ergoplatform.network.ModePeerFeature import org.ergoplatform.nodeView.history.{ErgoSyncInfo, ErgoSyncInfoV1, ErgoSyncInfoV2} import org.ergoplatform.nodeView.state.StateType import org.ergoplatform.settings.{Constants, ErgoValidationSettings, ErgoValidationSettingsUpdate, ValidationRules} -import org.ergoplatform.testkit.generators.CoreGenerators -import org.ergoplatform.utils.ErgoTestConstants import sigma.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule} -import org.ergoplatform.wallet.utils.Generators import org.scalacheck.Arbitrary.arbByte import org.scalacheck.{Arbitrary, Gen} import scorex.crypto.authds.{ADDigest, SerializedAdProof} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreTransactionGenerators.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreTransactionGenerators.scala index 40a748d7c4..e17ebe3d03 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreTransactionGenerators.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreTransactionGenerators.scala @@ -13,10 +13,10 @@ import org.ergoplatform._ import org.scalacheck.Gen import scorex.crypto.hash.Blake2b256 import scorex.util.ScorexLogging -import sigmastate.Values.ErgoTree -import sigmastate.crypto.DLogProtocol.ProveDlog +import sigma.ast.ErgoTree +import sigma.data.ProveDlog +import sigma.eval.Extensions._ import sigmastate.eval.Extensions._ -import sigmastate.eval._ import scala.collection.JavaConverters._ import scala.collection.mutable @@ -48,7 +48,7 @@ object ErgoCoreTransactionGenerators extends ScorexLogging { ar <- additionalRegistersGen tokens <- additionalTokensGen value <- validValueGen - } yield new ErgoBoxCandidate(value, prop, h, tokens.toColl, ar) + } yield new ErgoBoxCandidate(value, ErgoTree.fromSigmaBoolean(prop), h, tokens.toColl, ar) lazy val ergoBoxGenNoProp: Gen[ErgoBox] = ergoBoxGen(propGen = trueLeafGen) diff --git a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/utils/WalletGenerators.scala b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/utils/WalletGenerators.scala index 0674602a6a..4731f8a3c4 100644 --- a/ergo-wallet/src/test/scala/org/ergoplatform/wallet/utils/WalletGenerators.scala +++ b/ergo-wallet/src/test/scala/org/ergoplatform/wallet/utils/WalletGenerators.scala @@ -3,7 +3,6 @@ package org.ergoplatform.wallet.utils import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, TokenId} import org.ergoplatform.sdk.wallet.secrets._ import org.ergoplatform.sdk.wallet.settings.EncryptionSettings -import org.ergoplatform.wallet.Constants import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId} import org.ergoplatform.wallet.boxes.TrackedBox import org.ergoplatform.wallet.mnemonic.{Mnemonic, WordList} @@ -16,10 +15,9 @@ import sigma.ast._ import sigma.ast.syntax._ import sigma.crypto.CryptoFacade.SecretKeyLength import sigma.data.ProveDlog -import sigma.util.Extensions.SigmaBooleanOps import sigmastate.eval.Extensions._ import sigmastate.helpers.TestingHelpers._ -import sigmastate.{SByte, SType} +import sigma.eval.Extensions._ object WalletGenerators { @@ -177,7 +175,7 @@ object WalletGenerators { val dlog: Gen[ErgoTree] = Gen.const( ErgoTree.fromProposition( - secret.privateInput.publicImage.asInstanceOf[ProveDlog].toSigmaProp)) + secret.privateInput.publicImage.asInstanceOf[ProveDlog].toSigmaPropValue)) for { ins <- Gen.listOfN(2, ergoBoxGen(dlog)) diff --git a/src/it/scala/org/ergoplatform/it/WalletSpec.scala b/src/it/scala/org/ergoplatform/it/WalletSpec.scala index 344b165e49..3c239eccd0 100644 --- a/src/it/scala/org/ergoplatform/it/WalletSpec.scala +++ b/src/it/scala/org/ergoplatform/it/WalletSpec.scala @@ -25,7 +25,6 @@ import org.scalatest.wordspec.AsyncWordSpec import scorex.util.ModifierId import scorex.util.encode.Base16 import sigma.Colls -import sigmastate.Values.{ErgoTree, TrueLeaf} import scala.concurrent.ExecutionContext From 2616e249d75f1ad5fe5f0cc7b8bdcfee05cef3c1 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 10 Apr 2024 19:26:50 +0100 Subject: [PATCH 07/36] sigma-5.0.14: fixes after merge: tests --- src/it/scala/org/ergoplatform/it/WalletSpec.scala | 11 ++++------- .../modifiers/mempool/ErgoNodeTransactionSpec.scala | 6 +++--- .../nodeView/mempool/ErgoMemPoolSpec.scala | 1 - .../ergoplatform/nodeView/mempool/ScriptsSpec.scala | 10 ++++------ .../nodeView/state/ErgoStateSpecification.scala | 2 +- .../nodeView/state/UtxoStateSpecification.scala | 2 +- .../nodeView/wallet/ErgoWalletServiceSpec.scala | 2 +- .../nodeView/wallet/WalletScanLogicSpec.scala | 2 -- .../serialization/JsonSerializationSpec.scala | 11 +++-------- src/test/scala/org/ergoplatform/utils/Stubs.scala | 8 +++----- .../generators/ErgoNodeTransactionGenerators.scala | 7 +++---- 11 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/it/scala/org/ergoplatform/it/WalletSpec.scala b/src/it/scala/org/ergoplatform/it/WalletSpec.scala index 3c239eccd0..4633f219a5 100644 --- a/src/it/scala/org/ergoplatform/it/WalletSpec.scala +++ b/src/it/scala/org/ergoplatform/it/WalletSpec.scala @@ -10,11 +10,7 @@ import org.ergoplatform.it.api.NodeApi.UnexpectedStatusCodeException import org.ergoplatform.it.container.{IntegrationSuite, Node} import org.ergoplatform.it.util.RichEither import org.ergoplatform.modifiers.mempool.UnsignedErgoTransaction -import org.ergoplatform.nodeView.wallet.requests.{ - PaymentRequest, - RequestsHolder, - RequestsHolderEncoder -} +import org.ergoplatform.nodeView.wallet.requests.{PaymentRequest, RequestsHolder, RequestsHolderEncoder} import org.ergoplatform.nodeView.wallet.{AugWalletTransaction, ErgoWalletServiceImpl} import org.ergoplatform.settings.{Args, ErgoSettings, ErgoSettingsReader} import org.ergoplatform.utils.{ErgoTestHelpers, WalletTestOps} @@ -25,6 +21,8 @@ import org.scalatest.wordspec.AsyncWordSpec import scorex.util.ModifierId import scorex.util.encode.Base16 import sigma.Colls +import sigma.ast.ErgoTree +import sigma.data.TrivialProp.TrueProp import scala.concurrent.ExecutionContext @@ -103,13 +101,12 @@ class WalletSpec } "it should generate unsigned transaction" in { - import sigmastate.eval._ val mnemonic = SecretString.create(walletAutoInitConfig.getString("ergo.wallet.testMnemonic")) val prover = new ErgoWalletServiceImpl(settings) .buildProverFromMnemonic(mnemonic, None, parameters) val pk = prover.hdPubKeys.head.key - val ergoTree = ErgoTree.fromProposition(TrueLeaf) + val ergoTree = ErgoTree.fromProposition(TrueProp) val transactionId = ModifierId @@ Base16.encode(Array.fill(32)(5: Byte)) val input = new ErgoBox( 60000000, diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala index 47aa907efe..b6be483804 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala @@ -18,9 +18,9 @@ import org.ergoplatform.wallet.protocol.context.InputContext import org.scalacheck.Gen import sigma.util.BenchmarkUtil import scorex.crypto.hash.Blake2b256 -import sigmastate.AND +import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast.{AND, ErgoTree, TrueLeaf} import sigmastate.helpers.TestingHelpers._ -import sigmastate.Values.TrueLeaf import scala.util.{Random, Try} @@ -444,7 +444,7 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { forAll(smallPositiveInt) { inputsNum => - val nonTrivialTrueGen = Gen.const(AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp.treeWithSegregation) + val nonTrivialTrueGen = Gen.const(ErgoTree.withSegregation(ZeroHeader, AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp)) val gen = validErgoTransactionGenTemplate(0, 0, inputsNum, nonTrivialTrueGen) val (from, tx) = gen.sample.get tx.statelessValidity().isSuccess shouldBe true diff --git a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala index d166dad024..4dbfeb1573 100644 --- a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala @@ -5,7 +5,6 @@ import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.{ProcessingOutcome, So import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.settings.ErgoSettings import org.ergoplatform.utils.ErgoTestHelpers -import org.ergoplatform.utils.generators.ErgoGenerators import org.ergoplatform.{ErgoBoxCandidate, Input} import org.scalatest.flatspec.AnyFlatSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks diff --git a/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala b/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala index f22c0fd53e..034f6dd2a6 100644 --- a/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala @@ -4,27 +4,25 @@ import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix import org.ergoplatform.ErgoTreePredef.boxCreationHeight import org.ergoplatform.nodeView.state.{BoxHolder, ErgoState, UtxoState} import org.ergoplatform.settings.Algos -import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} -import org.ergoplatform.{ErgoBox, ErgoTreePredef} import org.ergoplatform.utils.{ErgoCorePropertyTest, RandomWrapper} import org.ergoplatform.wallet.utils.FileUtils -import org.ergoplatform.{ErgoBox, ErgoTreePredef, Height, Self} +import org.ergoplatform.{ErgoBox, ErgoTreePredef} import scorex.crypto.authds.avltree.batch.Remove import sigma.ast.syntax.ValueOps import sigma.ast.{TransformingSigmaBuilder, _} -import sigmastate._ import sigma.crypto.CryptoConstants.dlogGroup import sigma.data.ProveDlog +import sigmastate._ import sigmastate.eval.{CompiletimeIRContext, IRContext} import sigmastate.lang.{CompilerSettings, SigmaCompiler} import scala.util.Try class ScriptsSpec extends ErgoCorePropertyTest with FileUtils { - import org.ergoplatform.utils.ErgoNodeTestConstants._ import org.ergoplatform.utils.ErgoCoreTestConstants._ - import org.ergoplatform.wallet.utils.WalletGenerators._ + import org.ergoplatform.utils.ErgoNodeTestConstants._ import org.ergoplatform.utils.generators.ValidBlocksGenerators._ + import org.ergoplatform.wallet.utils.WalletGenerators._ val compiler = SigmaCompiler( CompilerSettings(TestnetNetworkPrefix, TransformingSigmaBuilder, lowerMethodCalls = true) diff --git a/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala index 11e53bcf18..d61fd82fbb 100644 --- a/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala @@ -9,6 +9,7 @@ import org.ergoplatform.utils.{ErgoCorePropertyTest, RandomWrapper} import org.ergoplatform.wallet.boxes.ErgoBoxSerializer import org.scalacheck.Gen import org.ergoplatform.core.bytesToVersion +import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators.boxesHolderGen import org.ergoplatform.validation.ValidationResult.Valid import scorex.db.ByteArrayWrapper @@ -18,7 +19,6 @@ import scala.util.{Failure, Try} class ErgoStateSpecification extends ErgoCorePropertyTest { import org.ergoplatform.utils.ErgoNodeTestConstants._ import org.ergoplatform.utils.ErgoCoreTestConstants._ - import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators._ import org.ergoplatform.utils.generators.ErgoCoreTransactionGenerators._ import org.ergoplatform.utils.generators.ValidBlocksGenerators._ diff --git a/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala index b9beddc0bf..c8f361d673 100644 --- a/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala @@ -14,6 +14,7 @@ import org.ergoplatform.modifiers.transaction.TooHighCostError import org.ergoplatform.core.idToVersion import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.settings.Constants +import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators.boxesHolderGen import org.ergoplatform.utils.{ErgoCorePropertyTest, RandomWrapper} import org.scalatest.OptionValues import scorex.crypto.authds.ADKey @@ -33,7 +34,6 @@ import scala.util.Try class UtxoStateSpecification extends ErgoCorePropertyTest with OptionValues { import org.ergoplatform.utils.ErgoNodeTestConstants._ import org.ergoplatform.utils.ErgoCoreTestConstants._ - import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators._ import org.ergoplatform.utils.generators.ErgoCoreTransactionGenerators._ import org.ergoplatform.utils.generators.ErgoCoreGenerators._ import org.ergoplatform.utils.generators.ValidBlocksGenerators._ diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala index 42f6d42314..e3c4c00638 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala @@ -12,6 +12,7 @@ import org.ergoplatform.nodeView.wallet.scanning.{EqualsScanningPredicate, ScanR import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey} import org.ergoplatform.settings.ErgoSettings import org.ergoplatform.utils.fixtures.WalletFixture +import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators.validErgoTransactionGen import org.ergoplatform.utils.{ErgoCorePropertyTest, MempoolTestHelpers, WalletTestOps} import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId} import org.ergoplatform.wallet.boxes.BoxSelector.BoxSelectionResult @@ -42,7 +43,6 @@ class ErgoWalletServiceSpec import org.ergoplatform.utils.generators.ErgoNodeWalletGenerators._ import org.ergoplatform.utils.generators.CoreObjectGenerators._ import org.ergoplatform.utils.generators.ErgoCoreGenerators._ - import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators._ import org.ergoplatform.utils.generators.ErgoCoreTransactionGenerators._ override val ergoSettings: ErgoSettings = settings diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala index bc73f5c58e..cad46f9749 100644 --- a/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala @@ -4,10 +4,8 @@ import org.ergoplatform.utils.{ErgoCorePropertyTest, WalletTestOps} import WalletScanLogic.{extractWalletOutputs, scanBlockTransactions} import org.ergoplatform.db.DBSpec import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.wallet.WalletScanLogic.{extractWalletOutputs, scanBlockTransactions} import org.ergoplatform.nodeView.wallet.persistence.{OffChainRegistry, WalletRegistry} import org.ergoplatform.nodeView.wallet.scanning.{EqualsScanningPredicate, ScanRequest, ScanWalletInteraction} -import org.ergoplatform.utils.{ErgoPropertyTest, WalletTestOps} import org.ergoplatform.wallet.Constants import org.ergoplatform.wallet.Constants.ScanId import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input} diff --git a/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala b/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala index c780b4d910..ce1ede7eae 100644 --- a/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala +++ b/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala @@ -7,14 +7,9 @@ import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.history.popow.NipopowProof import org.ergoplatform.modifiers.mempool.UnsignedErgoTransaction import org.ergoplatform.nodeView.wallet.requests._ -import org.ergoplatform.sdk.wallet.secrets.{DhtSecretKey, DlogSecretKey} -import org.ergoplatform.settings.{Algos, ErgoSettingsReader} -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.utils.generators.WalletGenerators -import org.ergoplatform.wallet.Constants.ScanId -import org.ergoplatform.wallet.boxes.TrackedBox -import org.scalatest.Inspectors -import sigma.ast.{ErgoTree, EvaluatedValue, SType} +import org.ergoplatform.settings.ErgoSettingsReader +import org.ergoplatform.utils.ErgoCorePropertyTest +import org.scalatest.{EitherValues, Inspectors} import scala.util.Random diff --git a/src/test/scala/org/ergoplatform/utils/Stubs.scala b/src/test/scala/org/ergoplatform/utils/Stubs.scala index 56e1f5af64..1414789dae 100644 --- a/src/test/scala/org/ergoplatform/utils/Stubs.scala +++ b/src/test/scala/org/ergoplatform/utils/Stubs.scala @@ -27,8 +27,8 @@ import org.ergoplatform.sanity.ErgoSanity.HT import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey} import org.ergoplatform.settings.Constants.HashLength import org.ergoplatform.settings._ -import org.ergoplatform.utils.generators.{ChainGenerator, ErgoGenerators, ErgoTransactionGenerators} -import org.ergoplatform.settings.{ScorexSettings, _} +import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators +import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators.{augWalletTransactionForScanGen, augWalletTransactionGen, boxesHolderGen} import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId} import org.ergoplatform.wallet.boxes.{ChainStatus, TrackedBox} import org.ergoplatform.wallet.interface4j.SecretString @@ -37,7 +37,6 @@ import org.ergoplatform.wallet.mnemonic.Mnemonic import org.ergoplatform.wallet.utils.TestFileUtils import org.scalacheck.Gen import scorex.core.network.NetworkController.ReceivableMessages.GetConnectedPeers -import org.ergoplatform.network.peer.PeerManager.ReceivableMessages.{GetAllPeers, GetBlacklistedPeers} import scorex.crypto.authds.ADDigest import scorex.crypto.hash.Digest32 import scorex.db.ByteArrayWrapper @@ -53,7 +52,6 @@ trait Stubs extends ErgoTestHelpers with TestFileUtils { import org.ergoplatform.utils.ErgoNodeTestConstants._ import org.ergoplatform.utils.ErgoCoreTestConstants._ import org.ergoplatform.utils.generators.ChainGenerator._ - import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators._ import org.ergoplatform.utils.generators.ErgoCoreTransactionGenerators._ import org.ergoplatform.utils.generators.ErgoCoreGenerators._ import org.ergoplatform.utils.generators.CoreObjectGenerators._ @@ -67,7 +65,7 @@ trait Stubs extends ErgoTestHelpers with TestFileUtils { val history: HT = applyChain(generateHistory(), chain) val digestState: DigestState = { - boxesHolderGen.map(WrappedUtxoState(_, createTempDir, None, parameters, settings)).map { wus => + ErgoNodeTransactionGenerators.boxesHolderGen.map(WrappedUtxoState(_, createTempDir, None, parameters, settings)).map { wus => DigestState.create(Some(wus.version), Some(wus.rootDigest), createTempDir, settings) } }.sample.value diff --git a/src/test/scala/org/ergoplatform/utils/generators/ErgoNodeTransactionGenerators.scala b/src/test/scala/org/ergoplatform/utils/generators/ErgoNodeTransactionGenerators.scala index 7deaa726db..d995abf542 100644 --- a/src/test/scala/org/ergoplatform/utils/generators/ErgoNodeTransactionGenerators.scala +++ b/src/test/scala/org/ergoplatform/utils/generators/ErgoNodeTransactionGenerators.scala @@ -1,5 +1,6 @@ package org.ergoplatform.utils.generators +import org.ergoplatform.ErgoBox.TokenId import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.nodeView.state.{BoxHolder, ErgoStateContext} @@ -11,7 +12,9 @@ import org.ergoplatform.utils.{BoxUtils, RandomLike, RandomWrapper} import org.ergoplatform.sdk.wallet.Constants.MaxAssetsPerBox import org.ergoplatform.wallet.interpreter.TransactionHintsBag import org.ergoplatform._ +import org.ergoplatform.nodeView.history.ErgoHistoryUtils.EmptyHistoryHeight import org.ergoplatform.wallet.Constants.ScanId +import org.ergoplatform.wallet.utils.WalletGenerators.{additionalRegistersGen, additionalTokensGen, boxIdGen, ergoBoxGen, validValueGen} import org.scalacheck.Gen import scorex.db.ByteArrayWrapper import scorex.util.ScorexLogging @@ -22,7 +25,6 @@ import sigmastate.eval.Extensions._ import sigmastate.helpers.TestingHelpers._ import sigma.eval.Extensions.EvalIterableOps -import scala.collection.JavaConverters._ import scala.collection.mutable import scala.util.Random @@ -32,9 +34,6 @@ object ErgoNodeTransactionGenerators extends ScorexLogging { import org.ergoplatform.utils.ErgoNodeTestConstants._ import org.ergoplatform.utils.generators.ErgoCoreTransactionGenerators._ - protected implicit val addressEncoder: ErgoAddressEncoder = - ErgoAddressEncoder(settings.chainSettings.addressPrefix) - val creationHeightGen: Gen[Int] = Gen.choose(0, Int.MaxValue / 2) lazy val ergoBoxCandidateGen: Gen[ErgoBoxCandidate] = for { From ed207e4e361ba2c1bfdc54d279bb29a2b21b3287 Mon Sep 17 00:00:00 2001 From: jellymlg Date: Wed, 10 Apr 2024 21:41:35 +0200 Subject: [PATCH 08/36] Fix crash --- .../nodeView/history/extra/ExtraIndexer.scala | 53 ++++++++++--------- .../nodeView/history/extra/IndexerState.scala | 1 + 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala index dbda566f34..ecabf92d16 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala @@ -25,7 +25,7 @@ import spire.syntax.all.cfor import java.util.concurrent.ConcurrentHashMap import scala.collection.mutable import scala.collection.concurrent -import scala.concurrent.{ExecutionContextExecutor, Future} +import scala.concurrent.Future import scala.jdk.CollectionConverters._ /** @@ -33,8 +33,6 @@ import scala.jdk.CollectionConverters._ */ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { - private implicit val ec: ExecutionContextExecutor = context.dispatcher - /** * Max buffer size (determined by config) */ @@ -86,22 +84,22 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { * @param height - blockheight to get transations from * @return transactions at height */ - private def getBlockTransactionsAt(height: Int): BlockTransactions = { - val txs = blockCache.remove(height).getOrElse(history.bestBlockTransactionsAt(height).get) - if (height % 1000 == 0) blockCache.keySet.filter(_ < height).map(blockCache.remove) - if (readingUpTo - height < 300 && chainHeight - height > 1000) { - readingUpTo = math.min(height + 1001, chainHeight) - val blockNums = height + 1 to readingUpTo by 50 - blockNums.zip(blockNums.tail).map { range => // ranges of 50 blocks for each thread to read - Future { - (range._1 until range._2).foreach { blockNum => - blockCache.put(blockNum, history.bestBlockTransactionsAt(blockNum).get) - } + private def getBlockTransactionsAt(height: Int): Option[BlockTransactions] = + blockCache.remove(height).orElse(history.bestBlockTransactionsAt(height)).map { txs => + if (height % 1000 == 0) blockCache.keySet.filter(_ < height).map(blockCache.remove) + if (readingUpTo - height < 300 && chainHeight - height > 1000) { + readingUpTo = math.min(height + 1001, chainHeight) + val blockNums = height + 1 to readingUpTo by 50 + blockNums.zip(blockNums.tail).map { range => // ranges of 50 blocks for each thread to read + Future { + (range._1 until range._2).foreach { blockNum => + history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) + } + }(context.dispatcher) } } + txs } - txs - } /** * Spend an IndexedErgoBox from buffer or database. Also record tokens for later use in balance tracking logic. @@ -149,7 +147,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { } case None => // address not found at all spendOrReceive match { - case Left(iEb) => log.warn(s"Unknown address spent box ${bytesToId(iEb.box.id)}") // spend box should never happen by an unknown address + case Left(iEb) => log.error(s"Unknown address spent box ${bytesToId(iEb.box.id)}") // spend box should never happen by an unknown address case Right(iEb) => trees.put(id, IndexedErgoAddress(id).initBalance.addTx(state.globalTxIndex).addBox(iEb)) // receive box, new address } } @@ -176,7 +174,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { case Right(iEb) => tokens.put(id, x.addBox(iEb)) // receive box } case None => // token not found at all - log.warn(s"Unknown token $id") // spend box should never happen by an unknown token + log.error(s"Unknown token $id") // spend box should never happen by an unknown token } } @@ -234,18 +232,25 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { * @param headerOpt - header to index blocktransactions of (used after caught up with chain) */ protected def index(state: IndexerState, headerOpt: Option[Header] = None): IndexerState = { - val bt = headerOpt.flatMap { header => + val btOpt = headerOpt.flatMap { header => history.typedModifierById[BlockTransactions](header.transactionsId) - }.getOrElse(getBlockTransactionsAt(state.indexedHeight)) + }.orElse(getBlockTransactionsAt(state.indexedHeight)) val height = headerOpt.map(_.height).getOrElse(state.indexedHeight) + if(btOpt.isEmpty) { + log.warn(s"Could not read block $height / $chainHeight from database, waiting for new block until retrying") + return state.decrementIndexedHeight.copy(caughtUp = true) + } + + val txs: Seq[ErgoTransaction] = btOpt.get.txs + var boxCount: Int = 0 implicit var newState: IndexerState = state // record transactions and boxes - cfor(0)(_ < bt.txs.length, _ + 1) { n => + cfor(0)(_ < txs.length, _ + 1) { n => - val tx: ErgoTransaction = bt.txs(n) + val tx: ErgoTransaction = txs(n) val inputs: Array[Long] = Array.ofDim[Long](tx.inputs.length) val outputs: Array[Long] = Array.ofDim[Long](tx.outputs.length) @@ -302,7 +307,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { } - log.info(s"Buffered block $height / $chainHeight [txs: ${bt.txs.length}, boxes: $boxCount] (buffer: $modCount / $saveLimit)") + log.info(s"Buffered block $height / $chainHeight [txs: ${txs.length}, boxes: $boxCount] (buffer: $modCount / $saveLimit)") val maxHeight = headerOpt.map(_.height).getOrElse(chainHeight) newState.copy(caughtUp = newState.indexedHeight == maxHeight) @@ -314,7 +319,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { * @param state - current state of indexer * @param height - starting height */ - protected def removeAfter(state: IndexerState, height: Int): IndexerState = { + private def removeAfter(state: IndexerState, height: Int): IndexerState = { var newState: IndexerState = state diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexerState.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexerState.scala index 05dec8d177..30f8fc4eeb 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexerState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexerState.scala @@ -20,6 +20,7 @@ case class IndexerState(indexedHeight: Int, def rollbackInProgress: Boolean = rollbackTo > 0 def incrementIndexedHeight: IndexerState = copy(indexedHeight = indexedHeight + 1) + def decrementIndexedHeight: IndexerState = copy(indexedHeight = indexedHeight - 1) def incrementTxIndex: IndexerState = copy(globalTxIndex = globalTxIndex + 1) def incrementBoxIndex: IndexerState = copy(globalBoxIndex = globalBoxIndex + 1) From 027beabe1d07444148de1345b9c7bf8968c3a7c6 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 12 Apr 2024 00:36:51 +0300 Subject: [PATCH 09/36] test for Soft-forked execution of Ergoscript containing unknown methods --- .../mempool/ErgoTransactionSpec.scala | 3 - .../mempool/ErgoNodeTransactionSpec.scala | 1048 ++++++++++------- 2 files changed, 653 insertions(+), 398 deletions(-) diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala index 003e2b0372..2a374b09fa 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala @@ -83,8 +83,6 @@ class ErgoTransactionSpec extends ErgoCorePropertyTest { "{\"id\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"inputs\":[{\"boxId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"spendingProof\":{\"proofBytes\":\"\",\"extension\":{}}},{\"boxId\":\"2e9798d7eb0cd867f6dc29872f80de64c04cef10a99a58d007ef7855f0acbdb9\",\"spendingProof\":{\"proofBytes\":\"\",\"extension\":{}}}],\"dataInputs\":[{\"boxId\":\"f97d1dc4626de22db836270fe1aa004b99970791e4557de8f486f6d433b81195\"}],\"outputs\":[{\"boxId\":\"69e05b68715caaa4ca58ba59a8c8c7e031d42ad890b05f87021a28617c1e70d5\",\"value\":524940416256346,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[{\"tokenId\":\"6df03fffc9042bf0edb0d0d36d7a675239b83a9080d39716b9aa0a64cccb9963\",\"amount\":226153050},{\"tokenId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"amount\":536110126}],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":0},{\"boxId\":\"556a9a3ec7880d468e56d44e75898cf8a32f6a07344895fa6b5cf34edf101a59\",\"value\":524940416256346,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[{\"tokenId\":\"6df03fffc9042bf0edb0d0d36d7a675239b83a9080d39716b9aa0a64cccb9963\",\"amount\":226153050},{\"tokenId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"amount\":536110126}],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":1},{\"boxId\":\"16385b5b83992629909c7e004ed0421229ed3587162ce6f29b2df129472e3909\",\"value\":1016367755463674,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":2}],\"size\":329}") } - - property("context extension with neg id") { val negId: Byte = -10 @@ -105,7 +103,6 @@ class ErgoTransactionSpec extends ErgoCorePropertyTest { txTry.toEither.left.get.isInstanceOf[NegativeArraySizeException] shouldBe true } - property("context extension with neg and pos ids") { val negId: Byte = -20 diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala index 47aa907efe..8df6473cf1 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala @@ -5,22 +5,27 @@ import org.ergoplatform.nodeView.state.{ErgoStateContext, VotingData} import org.ergoplatform.settings._ import org.ergoplatform.utils.ErgoCorePropertyTest import org.ergoplatform.wallet.interpreter.ErgoInterpreter -import org.ergoplatform.{ErgoBox, ErgoBoxCandidate} +import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input} import scorex.util.{ModifierId, bytesToId} import sigmastate.eval.Extensions._ import org.ergoplatform.nodeView.ErgoContext import org.ergoplatform.sdk.wallet.protocol.context.TransactionContext import org.ergoplatform.settings.Parameters.MaxBlockCostIncrease import org.ergoplatform.settings.ValidationRules.{bsBlockTransactionsCost, txAssetsInOneBox} +import org.ergoplatform.validation.ReplacedRule import org.ergoplatform.wallet.boxes.ErgoBoxAssetExtractor import org.ergoplatform.wallet.interpreter.TransactionHintsBag import org.ergoplatform.wallet.protocol.context.InputContext import org.scalacheck.Gen import sigma.util.BenchmarkUtil import scorex.crypto.hash.Blake2b256 +import scorex.util.encode.Base16 +import sigma.Colls import sigmastate.AND import sigmastate.helpers.TestingHelpers._ import sigmastate.Values.TrueLeaf +import sigmastate.interpreter.{ContextExtension, ProverResult} +import sigmastate.serialization.ErgoTreeSerializer import scala.util.{Random, Try} @@ -31,31 +36,38 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators._ import org.ergoplatform.utils.generators.ErgoCoreTransactionGenerators._ - private implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) + implicit private val verifier: ErgoInterpreter = ErgoInterpreter(parameters) private val emptyModifierId: ModifierId = bytesToId(Array.fill(32)(0.toByte)) - private def checkTx(from: IndexedSeq[ErgoBox], tx: ErgoTransaction): Try[Int] = { - tx.statelessValidity().flatMap(_ => tx.statefulValidity(from, emptyDataBoxes, emptyStateContext)) + tx.statelessValidity() + .flatMap(_ => tx.statefulValidity(from, emptyDataBoxes, emptyStateContext)) } - private def modifyValue(boxCandidate: ErgoBoxCandidate, delta: Long): ErgoBoxCandidate = { + private def modifyValue( + boxCandidate: ErgoBoxCandidate, + delta: Long + ): ErgoBoxCandidate = { new ErgoBoxCandidate( boxCandidate.value + delta, boxCandidate.ergoTree, boxCandidate.creationHeight, boxCandidate.additionalTokens, - boxCandidate.additionalRegisters) + boxCandidate.additionalRegisters + ) } - private def modifyAsset(boxCandidate: ErgoBoxCandidate, - deltaFn: Long => Long, - idToskip: TokenId): ErgoBoxCandidate = { + private def modifyAsset( + boxCandidate: ErgoBoxCandidate, + deltaFn: Long => Long, + idToskip: TokenId + ): ErgoBoxCandidate = { val assetId = boxCandidate.additionalTokens.find(t => t._1 != idToskip).get._1 - val tokens = boxCandidate.additionalTokens.map { case (id, amount) => - if (id == assetId) assetId -> deltaFn(amount) else assetId -> amount + val tokens = boxCandidate.additionalTokens.map { + case (id, amount) => + if (id == assetId) assetId -> deltaFn(amount) else assetId -> amount } new ErgoBoxCandidate( @@ -63,32 +75,51 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { boxCandidate.ergoTree, boxCandidate.creationHeight, tokens, - boxCandidate.additionalRegisters) + boxCandidate.additionalRegisters + ) } - private def updateAnAsset(tx: ErgoTransaction, from: IndexedSeq[ErgoBox], deltaFn: Long => Long) = { - val updCandidates = tx.outputCandidates.foldLeft(IndexedSeq[ErgoBoxCandidate]() -> false) { case ((seq, modified), ebc) => - if (modified) { - (seq :+ ebc) -> true - } else { - if (ebc.additionalTokens.nonEmpty && ebc.additionalTokens.exists(t => !java.util.Arrays.equals(t._1.toArray, from.head.id))) { - (seq :+ modifyAsset(ebc, deltaFn, from.head.id.toTokenId)) -> true - } else { - (seq :+ ebc) -> false - } + private def updateAnAsset( + tx: ErgoTransaction, + from: IndexedSeq[ErgoBox], + deltaFn: Long => Long + ) = { + val updCandidates = tx.outputCandidates + .foldLeft(IndexedSeq[ErgoBoxCandidate]() -> false) { + case ((seq, modified), ebc) => + if (modified) { + (seq :+ ebc) -> true + } else { + if (ebc.additionalTokens.nonEmpty && ebc.additionalTokens.exists(t => + !java.util.Arrays.equals(t._1.toArray, from.head.id) + )) { + (seq :+ modifyAsset(ebc, deltaFn, from.head.id.toTokenId)) -> true + } else { + (seq :+ ebc) -> false + } + } } - }._1 + ._1 tx.copy(outputCandidates = updCandidates) } property("monotonic creation height") { def stateContext(height: Int, blockVersion: Byte): ErgoStateContext = { - val header = defaultHeaderGen.sample.get.copy(version = blockVersion, height = height) - val params = Parameters(LaunchParameters.height, - LaunchParameters.parametersTable.updated(Parameters.BlockVersion, blockVersion), - LaunchParameters.proposedUpdate) - new ErgoStateContext(Seq(header), None, genesisStateDigest, params, ErgoValidationSettings.initial, - VotingData.empty)(settings.chainSettings) + val header = + defaultHeaderGen.sample.get.copy(version = blockVersion, height = height) + val params = Parameters( + LaunchParameters.height, + LaunchParameters.parametersTable.updated(Parameters.BlockVersion, blockVersion), + LaunchParameters.proposedUpdate + ) + new ErgoStateContext( + Seq(header), + None, + genesisStateDigest, + params, + ErgoValidationSettings.initial, + VotingData.empty + )(settings.chainSettings) } def stateContextForTx(tx: ErgoTransaction, blockVersion: Byte): ErgoStateContext = { @@ -96,386 +127,613 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { } def updateOutputHeight(box: ErgoBoxCandidate, value: Int): ErgoBoxCandidate = { - new ErgoBoxCandidate(box.value, box.ergoTree, value, box.additionalTokens, box.additionalRegisters) + new ErgoBoxCandidate( + box.value, + box.ergoTree, + value, + box.additionalTokens, + box.additionalRegisters + ) } def updateInputHeight(box: ErgoBox): ErgoBox = { val creationHeight = scala.util.Random.nextInt(1000) + 1 - new ErgoBox(box.value, box.ergoTree, box.additionalTokens, box.additionalRegisters, - box.transactionId, box.index, creationHeight) + new ErgoBox( + box.value, + box.ergoTree, + box.additionalTokens, + box.additionalRegisters, + box.transactionId, + box.index, + creationHeight + ) } // retuns random transaction along with inputs, // and a boolean flag, if the latter is true, monotonic creation height rule holds, // otherwise, it does not hold - val txGen = boxesGenTemplate(minAssets = 0, maxAssets = 5, minInputs = 5, maxInputs = 10, propositionGen = trueLeafGen).map { case (boxes, _) => - boxes.map(updateInputHeight) - }.map{ boxes => - val fixed = Random.nextBoolean() - val maxHeight = boxes.map(_.creationHeight).max - val preUnsignedTx = validUnsignedTransactionFromBoxes(boxes) - val unsignedTx = if(fixed) { - preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map{out => - val creationHeight = maxHeight + Random.nextInt(3) - updateOutputHeight(out, creationHeight) - }) - } else { - preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map{out => - val creationHeight = maxHeight - (Random.nextInt(maxHeight) + 1) - updateOutputHeight(out, creationHeight) - }) + val txGen = boxesGenTemplate( + minAssets = 0, + maxAssets = 5, + minInputs = 5, + maxInputs = 10, + propositionGen = trueLeafGen + ).map { + case (boxes, _) => + boxes.map(updateInputHeight) + } + .map { boxes => + val fixed = Random.nextBoolean() + val maxHeight = boxes.map(_.creationHeight).max + val preUnsignedTx = validUnsignedTransactionFromBoxes(boxes) + val unsignedTx = if (fixed) { + preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map { + out => + val creationHeight = maxHeight + Random.nextInt(3) + updateOutputHeight(out, creationHeight) + }) + } else { + preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map { + out => + val creationHeight = maxHeight - (Random.nextInt(maxHeight) + 1) + updateOutputHeight(out, creationHeight) + }) + } + val tx = defaultProver + .sign(unsignedTx, boxes, IndexedSeq.empty, emptyStateContext) + .map(ErgoTransaction.apply) + .get + (boxes, tx, fixed) } - val tx = defaultProver.sign(unsignedTx, boxes, IndexedSeq.empty, emptyStateContext) - .map(ErgoTransaction.apply) - .get - (boxes, tx, fixed) + + forAll(txGen) { + case (boxes, tx, fixed) => + // with initial block version == 1, monotonic rule does not work + tx.statefulValidity( + boxes, + IndexedSeq.empty, + stateContextForTx(tx, blockVersion = 1) + ) + .isSuccess shouldBe true + + // with pre-5.0 block version == 2, monotonic rule does not work as well + tx.statefulValidity( + boxes, + IndexedSeq.empty, + stateContextForTx(tx, blockVersion = 2) + ) + .isSuccess shouldBe true + + // starting from block version == 3, monotonic rule works, + // so validation fails if transaction is not following the rule (fixed == false) + val ctx3 = stateContextForTx(tx, blockVersion = 3) + if (fixed) { + tx.statefulValidity(boxes, IndexedSeq.empty, ctx3).isSuccess shouldBe true + } else { + val txFailure = tx.statefulValidity(boxes, IndexedSeq.empty, ctx3) + txFailure.isSuccess shouldBe false + val cause = txFailure.toEither.left.get.getMessage + val expectedMessage = ValidationRules.errorMessage( + ValidationRules.txMonotonicHeight, + "", + emptyModifierId, + ErgoTransaction.modifierTypeId + ) + cause should startWith(expectedMessage) + } + } + } + + property("a valid transaction is valid") { + forAll(validErgoTransactionGen) { + case (from, tx) => + tx.statelessValidity().isSuccess shouldBe true + tx.statefulValidity(from, emptyDataBoxes, emptyStateContext) + .isSuccess shouldBe true + } + } + + property("ergo preservation law holds") { + forAll(validErgoTransactionGen, smallPositiveInt) { + case ((from, tx), deltaAbs) => + val delta = if (Random.nextBoolean()) -deltaAbs else deltaAbs + + val wrongTx = tx.copy(outputCandidates = + modifyValue(tx.outputCandidates.head, delta) +: tx.outputCandidates.tail + ) + + wrongTx.statelessValidity().isSuccess && + wrongTx + .statefulValidity(from, emptyDataBoxes, emptyStateContext) + .isSuccess shouldBe false + } + } + + property("impossible to create a negative-value output") { + forAll(validErgoTransactionGen) { + case (from, tx) => + val negValue = Math.min( + Math.abs(Random.nextLong()), + Long.MaxValue - tx.outputCandidates.head.value + ) + val wrongTx = tx.copy(outputCandidates = + modifyValue( + tx.outputCandidates.head, + -(tx.outputCandidates.head.value + negValue) + ) +: tx.outputCandidates.tail + ) + + wrongTx.statelessValidity().isSuccess shouldBe false + wrongTx + .statefulValidity(from, emptyDataBoxes, emptyStateContext) + .isSuccess shouldBe false + } + } + + property("impossible to overflow ergo tokens") { + forAll(validErgoTransactionGen) { + case (from, tx) => + val overflowSurplus = (Long.MaxValue - tx.outputCandidates.map(_.value).sum) + 1 + + val wrongTx = tx.copy(outputCandidates = + modifyValue(tx.outputCandidates.head, overflowSurplus) +: tx.outputCandidates.tail + ) + + wrongTx.statelessValidity().isSuccess shouldBe false + wrongTx + .statefulValidity(from, emptyDataBoxes, emptyStateContext) + .isSuccess shouldBe false + } + } + + property("assets preservation law holds") { + forAll(validErgoTransactionWithAssetsGen) { + case (from, tx) => + checkTx(from, updateAnAsset(tx, from, _ + 1)) shouldBe 'failure + } + } + + property("impossible to create an asset of negative amount") { + forAll(validErgoTransactionWithAssetsGen) { + case (from, tx) => + checkTx(from, updateAnAsset(tx, from, _ => -1)) shouldBe 'failure + } + } + + property("impossible to create an asset of zero amount") { + forAll(validErgoTransactionWithAssetsGen) { + case (from, tx) => + checkTx(from, updateAnAsset(tx, from, _ => 0)) shouldBe 'failure + } + } + + property("impossible to overflow an asset value") { + val gen = validErgoTransactionGenTemplate( + minAssets = 1, + maxAssets = 1, + maxInputs = 16, + propositionGen = trueLeafGen + ) + forAll(gen) { + case (from, tx) => + val tokenOpt = tx.outputCandidates + .flatMap(_.additionalTokens.toArray) + .groupBy(_._1) + .find(_._2.size >= 2) + + whenever(tokenOpt.nonEmpty) { + val tokenId = tokenOpt.get._1 + val tokenAmount = tokenOpt.get._2.map(_._2).sum + + var modified = false + val updCandidates = tx.outputCandidates.map { c => + val updTokens = c.additionalTokens.map { + case (id, amount) => + if (!modified && id == tokenId) { + modified = true + id -> ((Long.MaxValue - tokenAmount) + amount + 1) + } else { + id -> amount + } + } + new ErgoBoxCandidate( + c.value, + c.ergoTree, + startHeight, + updTokens, + c.additionalRegisters + ) + } + + val wrongTx = tx.copy(outputCandidates = updCandidates) + checkTx(from, wrongTx) shouldBe 'failure + } } + } + + property("stateful validation should catch false proposition") { + val propositionGen = Gen.const(Constants.FalseLeaf) + val gen = validErgoTransactionGenTemplate(1, 1, 1, propositionGen) + forAll(gen) { + case (from, tx) => + tx.statelessValidity().isSuccess shouldBe true + val validity = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext) + validity.isSuccess shouldBe false + val e = validity.failed.get + e.getMessage should startWith( + ValidationRules.errorMessage( + ValidationRules.txScriptValidation, + "", + emptyModifierId, + ErgoTransaction.modifierTypeId + ) + ) + } + } + + property("assets usage correctly affects transaction total cost") { + val txGen = validErgoTransactionGenTemplate(1, 1, 16, propositionGen = trueLeafGen) + forAll(txGen) { + case (from, tx) => + val initTxCost = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext).get + + // already existing token from one of the inputs + val existingToken = from.flatMap(_.additionalTokens.toArray).toSet.head + // completely new token + val randomToken = + (scorex.util.Random.randomBytes().toTokenId, Random.nextInt(100000000).toLong) + + val in0 = from.last + // new token added to the last input + val modifiedIn0 = testBox( + in0.value, + in0.ergoTree, + in0.creationHeight, + in0.additionalTokens.toArray.toSeq :+ randomToken, + in0.additionalRegisters, + in0.transactionId, + in0.index + ) + val txInMod0 = tx.inputs.last.copy(boxId = modifiedIn0.id) + + val in1 = from.last + // existing token added to the last input + val modifiedIn1 = testBox( + in1.value, + in1.ergoTree, + in1.creationHeight, + in1.additionalTokens.toArray.toSeq :+ existingToken, + in1.additionalRegisters, + in1.transactionId, + in1.index + ) + val txInMod1 = tx.inputs.last.copy(boxId = modifiedIn1.id) + + val out0 = tx.outputs.last + // new token added to the last output + val modifiedOut0 = testBox( + out0.value, + out0.ergoTree, + out0.creationHeight, + out0.additionalTokens.toArray.toSeq :+ randomToken, + out0.additionalRegisters, + out0.transactionId, + out0.index + ) + // existing token added to the last output + val modifiedOut1 = testBox( + out0.value, + out0.ergoTree, + out0.creationHeight, + out0.additionalTokens.toArray.toSeq :+ existingToken, + out0.additionalRegisters, + out0.transactionId, + out0.index + ) + + // update transaction inputs and outputs accordingly + val txMod0 = tx.copy(inputs = tx.inputs.init :+ txInMod0) // new token group added to one input + val txMod1 = tx.copy(inputs = tx.inputs.init :+ txInMod1) // existing token added to one input + val txMod2 = tx.copy( + inputs = tx.inputs.init :+ txInMod0, // new token group added to one input and one output + outputCandidates = tx.outputCandidates.init :+ modifiedOut0 + ) + val txMod3 = tx.copy( + inputs = tx.inputs.init :+ txInMod1, // existing token added to one input and one output + outputCandidates = tx.outputCandidates.init :+ modifiedOut1 + ) + + val inputIncTxCost0 = txMod0 + .statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext) + .get + val inputIncTxCost1 = txMod1 + .statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext) + .get + val outputIncTxCost0 = txMod2 + .statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext) + .get + val outputIncTxCost1 = txMod3 + .statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext) + .get + + (inputIncTxCost0 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault * 2 // one more group + one more token in total + (inputIncTxCost1 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault // one more token in total + (outputIncTxCost0 - inputIncTxCost0) shouldEqual Parameters.TokenAccessCostDefault * 2 + (outputIncTxCost1 - inputIncTxCost1) shouldEqual Parameters.TokenAccessCostDefault + } + } - forAll(txGen){ case (boxes, tx, fixed) => - // with initial block version == 1, monotonic rule does not work - tx.statefulValidity(boxes, IndexedSeq.empty, stateContextForTx(tx, blockVersion = 1)).isSuccess shouldBe true - - // with pre-5.0 block version == 2, monotonic rule does not work as well - tx.statefulValidity(boxes, IndexedSeq.empty, stateContextForTx(tx, blockVersion = 2)).isSuccess shouldBe true - - // starting from block version == 3, monotonic rule works, - // so validation fails if transaction is not following the rule (fixed == false) - val ctx3 = stateContextForTx(tx, blockVersion = 3) - if (fixed) { - tx.statefulValidity(boxes, IndexedSeq.empty, ctx3).isSuccess shouldBe true - } else { - val txFailure = tx.statefulValidity(boxes, IndexedSeq.empty, ctx3) - txFailure.isSuccess shouldBe false - val cause = txFailure.toEither.left.get.getMessage - val expectedMessage = ValidationRules.errorMessage(ValidationRules.txMonotonicHeight, "", emptyModifierId, ErgoTransaction.modifierTypeId) - cause should startWith(expectedMessage) + property( + "spam simulation (transaction validation cost with too many tokens exceeds block limit)" + ) { + val bxsQty = 392 // with greater value test is failing with collection size exception + val (inputs, tx) = validErgoTransactionGenTemplate(1, 1, 16).sample.get // it takes too long to test with `forAll` + val tokens = + (0 until 255).map(_ => (scorex.util.Random.randomBytes().toTokenId, Random.nextLong) + ) + val (in, out) = { + val in0 = inputs.head + val out0 = tx.outputs.head + val inputsMod = (0 until bxsQty).map { i => + testBox( + 10000000000L, + in0.ergoTree, + in0.creationHeight, + tokens, + in0.additionalRegisters, + in0.transactionId, + i.toShort + ) + } + val outputsMod = (0 until bxsQty).map { i => + testBox( + 10000000000L, + out0.ergoTree, + out0.creationHeight, + tokens, + out0.additionalRegisters, + out0.transactionId, + i.toShort + ) } + inputsMod -> outputsMod + } + val inputsPointers = { + val inSample = tx.inputs.head + (0 until bxsQty).map(i => inSample.copy(boxId = in(i).id)) + } + val txMod = tx.copy(inputs = inputsPointers, outputCandidates = out) + val validFailure = txMod.statefulValidity(in, emptyDataBoxes, emptyStateContext) + validFailure.failed.get.getMessage should startWith( + ValidationRules + .errorMessage( + txAssetsInOneBox, + "", + emptyModifierId, + ErgoTransaction.modifierTypeId + ) + .take(30) + ) + } + + property("transaction with too many inputs should be rejected") { + + //we assume that verifier must finish verification of any script in less time than 250K hash calculations + // (for the Blake2b256 hash function over a single block input) + val Timeout: Long = { + val hf = Blake2b256 + + //just in case to heat up JVM + (1 to 5000000).foreach(i => hf(s"$i-$i")) + + val t0 = System.currentTimeMillis() + (1 to 250000).foreach(i => hf(s"$i")) + val t = System.currentTimeMillis() + t - t0 + } + + val gen = validErgoTransactionGenTemplate(0, 0, 2000, trueLeafGen) + val (from, tx) = gen.sample.get + tx.statelessValidity().isSuccess shouldBe true + + //check that spam transaction is being rejected quickly + implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) + val (validity, time0) = BenchmarkUtil.measureTime( + tx.statefulValidity(from, IndexedSeq(), emptyStateContext) + ) + validity.isSuccess shouldBe false + assert(time0 <= Timeout) + + val cause = validity.failed.get.getMessage + cause should startWith( + ValidationRules + .errorMessage( + bsBlockTransactionsCost, + "", + emptyModifierId, + ErgoTransaction.modifierTypeId + ) + .take(30) + ) + + //check that spam transaction validation with no cost limit is indeed taking too much time + import Parameters._ + val maxCost = (Int.MaxValue - 10) / 10 // cannot use Int.MaxValue directly due to overflow when it is converted to block cost + val ps = Parameters( + 0, + DefaultParameters.updated(MaxBlockCostIncrease, maxCost), + emptyVSUpdate + ) + val sc = new ErgoStateContext( + Seq.empty, + None, + genesisStateDigest, + ps, + ErgoValidationSettings.initial, + VotingData.empty + )(settings.chainSettings) + .upcoming( + org.ergoplatform.mining.group.generator, + 0L, + settings.chainSettings.initialNBits, + Array.fill(3)(0.toByte), + ErgoValidationSettingsUpdate.empty, + 0.toByte + ) + val (_, time) = BenchmarkUtil.measureTime( + tx.statefulValidity(from, IndexedSeq(), sc)(verifier) + ) + + assert(time > Timeout) + } + + property("transaction cost") { + def paramsWith(manualCost: Int) = Parameters( + 0, + Parameters.DefaultParameters + (MaxBlockCostIncrease -> manualCost), + ErgoValidationSettingsUpdate.empty + ) + + val gen = validErgoTransactionGenTemplate(0, 0, 10, trueLeafGen) + val (from, tx) = gen.sample.get + tx.statelessValidity().isSuccess shouldBe true + + // calculate costs manually + val initialCost: Long = + tx.inputs.size * parameters.inputCost + + tx.dataInputs.size * parameters.dataInputCost + + tx.outputs.size * parameters.outputCost + + ErgoInterpreter.interpreterInitCost + val (outAssets, outAssetsNum) = tx.outAssetsTry.get + val (inAssets, inAssetsNum) = ErgoBoxAssetExtractor.extractAssets(from).get + val totalAssetsAccessCost = + (outAssetsNum + inAssetsNum) * parameters.tokenAccessCost + + (inAssets.size + outAssets.size) * parameters.tokenAccessCost + val scriptsValidationCosts = tx.inputs.size + 1 // +1 for the block to JIT cost scaling + println(s"tx.inputs.size: ${tx.inputs.size}") + println( + s"initialCost + totalAssetsAccessCost: ${initialCost + totalAssetsAccessCost}" + ) + val approxCost: Int = + (initialCost + totalAssetsAccessCost + scriptsValidationCosts).toInt + + // check that validation pass if cost limit equals to approximated cost + val sc = stateContextWith(paramsWith(approxCost)) + sc.currentParameters.maxBlockCost shouldBe approxCost + val calculatedCost = tx + .statefulValidity(from, IndexedSeq(), sc)(ErgoInterpreter(sc.currentParameters)) + .get + approxCost - calculatedCost <= 1 shouldBe true + + // transaction exceeds computations limit + val sc2 = stateContextWith(paramsWith(approxCost - 1)) + tx.statefulValidity(from, IndexedSeq(), sc2)(ErgoInterpreter(sc2.currentParameters)) shouldBe 'failure + + // transaction exceeds computations limit due to non-zero accumulatedCost + tx.statefulValidity(from, IndexedSeq(), sc, accumulatedCost = 1)( + ErgoInterpreter(sc.currentParameters) + ) shouldBe 'failure + } + + property("cost accumulated correctly across inputs") { + val accInitCost = 100000 + + def inputCost(tx: ErgoTransaction, from: IndexedSeq[ErgoBox]): Long = { + val idx = 0 + val input = tx.inputs(idx) + val proof = input.spendingProof + val transactionContext = TransactionContext(from, IndexedSeq(), tx) + val inputContext = InputContext(idx.toShort, proof.extension) + + val ctx = new ErgoContext( + emptyStateContext, + transactionContext, + inputContext, + costLimit = emptyStateContext.currentParameters.maxBlockCost, + initCost = 0 + ) + + val messageToSign = tx.messageToSign + + val inputCost = + verifier.verify(from(idx).ergoTree, ctx, proof, messageToSign).get._2 + + inputCost } + + forAll(smallPositiveInt) { inputsNum => + val nonTrivialTrueGen = + Gen.const(AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp.treeWithSegregation) + val gen = validErgoTransactionGenTemplate(0, 0, inputsNum, nonTrivialTrueGen) + val (from, tx) = gen.sample.get + tx.statelessValidity().isSuccess shouldBe true + + tx.inputs.length shouldBe inputsNum + + val tokenAccessCost = emptyStateContext.currentParameters.tokenAccessCost + + val txCost = + tx.statefulValidity(from, IndexedSeq(), emptyStateContext, accInitCost).get + + val (inAssets, inAssetsNum): (Map[Seq[Byte], Long], Int) = + ErgoBoxAssetExtractor.extractAssets(from).get + val (outAssets, outAssetsNum): (Map[Seq[Byte], Long], Int) = + ErgoBoxAssetExtractor.extractAssets(tx.outputs).get + + val assetsCost = inAssetsNum * tokenAccessCost + inAssets.size * tokenAccessCost + + outAssetsNum * tokenAccessCost + outAssets.size * tokenAccessCost + + val unsignedTx = + UnsignedErgoTransaction(tx.inputs, tx.dataInputs, tx.outputCandidates) + val signerTxCost = + defaultProver + .signInputs( + unsignedTx, + from, + Vector.empty, + emptyStateContext, + TransactionHintsBag.empty + ) + .get + ._2 + + val signerTxCostWithInitCost = signerTxCost + accInitCost + signerTxCostWithInitCost shouldBe txCost // signer and verifier costs should be the same + + val initialCost: Long = + tx.inputs.size * parameters.inputCost + + tx.dataInputs.size * parameters.dataInputCost + + tx.outputs.size * parameters.outputCost + + ErgoInterpreter.interpreterInitCost + + assetsCost + + txCost shouldBe (accInitCost + initialCost + inputCost(tx, from) * inputsNum) + } + } + + property("Soft-forked execution of Ergoscript containing unknown methods") { + import ErgoTreeSerializer.DefaultSerializer + + val activatedVersion = 3.toByte + val params = new Parameters(0, LaunchParameters.parametersTable.updated(123, activatedVersion + 1), ErgoValidationSettingsUpdate.empty) + + val updVs = ErgoValidationSettings.initial.updated(ErgoValidationSettingsUpdate(Seq(), Seq(1011.toShort -> ReplacedRule(1011)))) + + val stateContext = emptyStateContext.copy(currentParameters = params, validationSettings = updVs)(chainSettings) + stateContext.blockVersion shouldBe activatedVersion + 1 + + val ergoTree = DefaultSerializer.deserializeErgoTree(Base16.decode("1b130206022edf0580fcf622d193db060873007301").get) + + val b = new ErgoBox(1000000000L, ergoTree, Colls.emptyColl, + Map.empty, ModifierId @@ "c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f7742", + 0, 0) + val input = Input(b.id, ProverResult(Array.emptyByteArray, ContextExtension.empty)) + + val oc = new ErgoBoxCandidate(b.value, b.ergoTree, b.creationHeight) + + val utx = new ErgoTransaction(IndexedSeq(input), IndexedSeq.empty, IndexedSeq(oc)) + + utx.statefulValidity(IndexedSeq(b), IndexedSeq.empty, stateContext, 0)(defaultProver).isSuccess shouldBe true } - property("a valid transaction is valid") { - forAll(validErgoTransactionGen) { case (from, tx) => - tx.statelessValidity().isSuccess shouldBe true - tx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe true - } - } - - property("ergo preservation law holds") { - forAll(validErgoTransactionGen, smallPositiveInt) { case ((from, tx), deltaAbs) => - val delta = if (Random.nextBoolean()) -deltaAbs else deltaAbs - - val wrongTx = tx.copy(outputCandidates = - modifyValue(tx.outputCandidates.head, delta) +: tx.outputCandidates.tail) - - wrongTx.statelessValidity().isSuccess && - wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false - } - } - - property("impossible to create a negative-value output") { - forAll(validErgoTransactionGen) { case (from, tx) => - val negValue = Math.min(Math.abs(Random.nextLong()), Long.MaxValue - tx.outputCandidates.head.value) - val wrongTx = tx.copy(outputCandidates = - modifyValue(tx.outputCandidates.head, -(tx.outputCandidates.head.value + negValue)) +: tx.outputCandidates.tail) - - wrongTx.statelessValidity().isSuccess shouldBe false - wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false - } - } - - property("impossible to overflow ergo tokens") { - forAll(validErgoTransactionGen) { case (from, tx) => - val overflowSurplus = (Long.MaxValue - tx.outputCandidates.map(_.value).sum) + 1 - - val wrongTx = tx.copy(outputCandidates = - modifyValue(tx.outputCandidates.head, overflowSurplus) +: tx.outputCandidates.tail) - - wrongTx.statelessValidity().isSuccess shouldBe false - wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false - } - } - - property("assets preservation law holds") { - forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ + 1)) shouldBe 'failure - } - } - - property("impossible to create an asset of negative amount") { - forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ => -1)) shouldBe 'failure - } - } - - property("impossible to create an asset of zero amount") { - forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ => 0)) shouldBe 'failure - } - } - - property("impossible to overflow an asset value") { - val gen = validErgoTransactionGenTemplate(minAssets = 1, maxAssets = 1, maxInputs = 16, propositionGen = trueLeafGen) - forAll(gen) { case (from, tx) => - val tokenOpt = tx.outputCandidates.flatMap(_.additionalTokens.toArray) - .groupBy(_._1).find(_._2.size >= 2) - - whenever(tokenOpt.nonEmpty) { - val tokenId = tokenOpt.get._1 - val tokenAmount = tokenOpt.get._2.map(_._2).sum - - var modified = false - val updCandidates = tx.outputCandidates.map { c => - val updTokens = c.additionalTokens.map { case (id, amount) => - if (!modified && id == tokenId) { - modified = true - id -> ((Long.MaxValue - tokenAmount) + amount + 1) - } else { - id -> amount - } - } - new ErgoBoxCandidate(c.value, c.ergoTree, startHeight, updTokens, c.additionalRegisters) - } - - val wrongTx = tx.copy(outputCandidates = updCandidates) - checkTx(from, wrongTx) shouldBe 'failure - } - } - } - - property("stateful validation should catch false proposition") { - val propositionGen = Gen.const(Constants.FalseLeaf) - val gen = validErgoTransactionGenTemplate(1, 1, 1, propositionGen) - forAll(gen) { case (from, tx) => - tx.statelessValidity().isSuccess shouldBe true - val validity = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext) - validity.isSuccess shouldBe false - val e = validity.failed.get - e.getMessage should startWith(ValidationRules.errorMessage(ValidationRules.txScriptValidation, "", emptyModifierId, ErgoTransaction.modifierTypeId)) - } - } - - property("assets usage correctly affects transaction total cost") { - val txGen = validErgoTransactionGenTemplate(1, 1,16, propositionGen = trueLeafGen) - forAll(txGen) { case (from, tx) => - val initTxCost = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext).get - - // already existing token from one of the inputs - val existingToken = from.flatMap(_.additionalTokens.toArray).toSet.head - // completely new token - val randomToken = (scorex.util.Random.randomBytes().toTokenId, Random.nextInt(100000000).toLong) - - val in0 = from.last - // new token added to the last input - val modifiedIn0 = testBox(in0.value, in0.ergoTree, in0.creationHeight, - in0.additionalTokens.toArray.toSeq :+ randomToken, in0.additionalRegisters, in0.transactionId, in0.index) - val txInMod0 = tx.inputs.last.copy(boxId = modifiedIn0.id) - - val in1 = from.last - // existing token added to the last input - val modifiedIn1 = testBox(in1.value, in1.ergoTree, in1.creationHeight, - in1.additionalTokens.toArray.toSeq :+ existingToken, in1.additionalRegisters, in1.transactionId, in1.index) - val txInMod1 = tx.inputs.last.copy(boxId = modifiedIn1.id) - - val out0 = tx.outputs.last - // new token added to the last output - val modifiedOut0 = testBox(out0.value, out0.ergoTree, out0.creationHeight, - out0.additionalTokens.toArray.toSeq :+ randomToken, out0.additionalRegisters, out0.transactionId, out0.index) - // existing token added to the last output - val modifiedOut1 = testBox(out0.value, out0.ergoTree, out0.creationHeight, - out0.additionalTokens.toArray.toSeq :+ existingToken, out0.additionalRegisters, out0.transactionId, out0.index) - - // update transaction inputs and outputs accordingly - val txMod0 = tx.copy(inputs = tx.inputs.init :+ txInMod0) // new token group added to one input - val txMod1 = tx.copy(inputs = tx.inputs.init :+ txInMod1) // existing token added to one input - val txMod2 = tx.copy(inputs = tx.inputs.init :+ txInMod0, // new token group added to one input and one output - outputCandidates = tx.outputCandidates.init :+ modifiedOut0) - val txMod3 = tx.copy(inputs = tx.inputs.init :+ txInMod1, // existing token added to one input and one output - outputCandidates = tx.outputCandidates.init :+ modifiedOut1) - - val inputIncTxCost0 = txMod0.statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext).get - val inputIncTxCost1 = txMod1.statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext).get - val outputIncTxCost0 = txMod2.statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext).get - val outputIncTxCost1 = txMod3.statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext).get - - (inputIncTxCost0 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault * 2 // one more group + one more token in total - (inputIncTxCost1 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault // one more token in total - (outputIncTxCost0 - inputIncTxCost0) shouldEqual Parameters.TokenAccessCostDefault * 2 - (outputIncTxCost1 - inputIncTxCost1) shouldEqual Parameters.TokenAccessCostDefault - } - } - - property("spam simulation (transaction validation cost with too many tokens exceeds block limit)") { - val bxsQty = 392 // with greater value test is failing with collection size exception - val (inputs, tx) = validErgoTransactionGenTemplate(1, 1,16).sample.get // it takes too long to test with `forAll` - val tokens = (0 until 255).map(_ => (scorex.util.Random.randomBytes().toTokenId, Random.nextLong)) - val (in, out) = { - val in0 = inputs.head - val out0 = tx.outputs.head - val inputsMod = (0 until bxsQty).map { i => - testBox(10000000000L, in0.ergoTree, in0.creationHeight, - tokens, in0.additionalRegisters, in0.transactionId, i.toShort) - } - val outputsMod = (0 until bxsQty).map { i => - testBox(10000000000L, out0.ergoTree, out0.creationHeight, - tokens, out0.additionalRegisters, out0.transactionId, i.toShort) - } - inputsMod -> outputsMod - } - val inputsPointers = { - val inSample = tx.inputs.head - (0 until bxsQty).map(i => inSample.copy(boxId = in(i).id)) - } - val txMod = tx.copy(inputs = inputsPointers, outputCandidates = out) - val validFailure = txMod.statefulValidity(in, emptyDataBoxes, emptyStateContext) - validFailure.failed.get.getMessage should startWith(ValidationRules.errorMessage(txAssetsInOneBox, "", emptyModifierId, ErgoTransaction.modifierTypeId).take(30)) - } - - property("transaction with too many inputs should be rejected") { - - //we assume that verifier must finish verification of any script in less time than 250K hash calculations - // (for the Blake2b256 hash function over a single block input) - val Timeout: Long = { - val hf = Blake2b256 - - //just in case to heat up JVM - (1 to 5000000).foreach(i => hf(s"$i-$i")) - - val t0 = System.currentTimeMillis() - (1 to 250000).foreach(i => hf(s"$i")) - val t = System.currentTimeMillis() - t - t0 - } - - val gen = validErgoTransactionGenTemplate(0, 0, 2000, trueLeafGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - //check that spam transaction is being rejected quickly - implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) - val (validity, time0) = BenchmarkUtil.measureTime(tx.statefulValidity(from, IndexedSeq(), emptyStateContext)) - validity.isSuccess shouldBe false - assert(time0 <= Timeout) - - val cause = validity.failed.get.getMessage - cause should startWith(ValidationRules.errorMessage(bsBlockTransactionsCost, "", emptyModifierId, ErgoTransaction.modifierTypeId).take(30)) - - //check that spam transaction validation with no cost limit is indeed taking too much time - import Parameters._ - val maxCost = (Int.MaxValue - 10) / 10 // cannot use Int.MaxValue directly due to overflow when it is converted to block cost - val ps = Parameters(0, DefaultParameters.updated(MaxBlockCostIncrease, maxCost), emptyVSUpdate) - val sc = new ErgoStateContext(Seq.empty, None, genesisStateDigest, ps, ErgoValidationSettings.initial, - VotingData.empty)(settings.chainSettings) - .upcoming(org.ergoplatform.mining.group.generator, - 0L, - settings.chainSettings.initialNBits, - Array.fill(3)(0.toByte), - ErgoValidationSettingsUpdate.empty, - 0.toByte) - val (_, time) = BenchmarkUtil.measureTime( - tx.statefulValidity(from, IndexedSeq(), sc)(verifier) - ) - - assert(time > Timeout) - } - - property("transaction cost") { - def paramsWith(manualCost: Int) = Parameters( - 0, - Parameters.DefaultParameters + (MaxBlockCostIncrease -> manualCost), - ErgoValidationSettingsUpdate.empty - ) - - val gen = validErgoTransactionGenTemplate(0, 0,10, trueLeafGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - // calculate costs manually - val initialCost: Long = - tx.inputs.size * parameters.inputCost + - tx.dataInputs.size * parameters.dataInputCost + - tx.outputs.size * parameters.outputCost + - ErgoInterpreter.interpreterInitCost - val (outAssets, outAssetsNum) = tx.outAssetsTry.get - val (inAssets, inAssetsNum) = ErgoBoxAssetExtractor.extractAssets(from).get - val totalAssetsAccessCost = - (outAssetsNum + inAssetsNum) * parameters.tokenAccessCost + - (inAssets.size + outAssets.size) * parameters.tokenAccessCost - val scriptsValidationCosts = tx.inputs.size + 1 // +1 for the block to JIT cost scaling - println(s"tx.inputs.size: ${tx.inputs.size}") - println(s"initialCost + totalAssetsAccessCost: ${initialCost + totalAssetsAccessCost}") - val approxCost: Int = (initialCost + totalAssetsAccessCost + scriptsValidationCosts).toInt - - - // check that validation pass if cost limit equals to approximated cost - val sc = stateContextWith(paramsWith(approxCost)) - sc.currentParameters.maxBlockCost shouldBe approxCost - val calculatedCost = tx.statefulValidity(from, IndexedSeq(), sc)(ErgoInterpreter(sc.currentParameters)).get - approxCost - calculatedCost <= 1 shouldBe true - - // transaction exceeds computations limit - val sc2 = stateContextWith(paramsWith(approxCost - 1)) - tx.statefulValidity(from, IndexedSeq(), sc2)(ErgoInterpreter(sc2.currentParameters)) shouldBe 'failure - - // transaction exceeds computations limit due to non-zero accumulatedCost - tx.statefulValidity(from, IndexedSeq(), sc, accumulatedCost = 1)(ErgoInterpreter(sc.currentParameters)) shouldBe 'failure - } - - property("cost accumulated correctly across inputs") { - val accInitCost = 100000 - - def inputCost(tx: ErgoTransaction, from: IndexedSeq[ErgoBox]): Long = { - val idx = 0 - val input = tx.inputs(idx) - val proof = input.spendingProof - val transactionContext = TransactionContext(from, IndexedSeq(), tx) - val inputContext = InputContext(idx.toShort, proof.extension) - - val ctx = new ErgoContext( - emptyStateContext, transactionContext, inputContext, - costLimit = emptyStateContext.currentParameters.maxBlockCost, - initCost = 0) - - val messageToSign = tx.messageToSign - - val inputCost = verifier.verify(from(idx).ergoTree, ctx, proof, messageToSign).get._2 - - inputCost - } - - forAll(smallPositiveInt) { inputsNum => - - val nonTrivialTrueGen = Gen.const(AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp.treeWithSegregation) - val gen = validErgoTransactionGenTemplate(0, 0, inputsNum, nonTrivialTrueGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - tx.inputs.length shouldBe inputsNum - - val tokenAccessCost = emptyStateContext.currentParameters.tokenAccessCost - - val txCost = tx.statefulValidity(from, IndexedSeq(), emptyStateContext, accInitCost).get - - val (inAssets, inAssetsNum): (Map[Seq[Byte], Long], Int) = ErgoBoxAssetExtractor.extractAssets(from).get - val (outAssets, outAssetsNum): (Map[Seq[Byte], Long], Int) = ErgoBoxAssetExtractor.extractAssets(tx.outputs).get - - val assetsCost = inAssetsNum * tokenAccessCost + inAssets.size * tokenAccessCost + - outAssetsNum * tokenAccessCost + outAssets.size * tokenAccessCost - - val unsignedTx = UnsignedErgoTransaction(tx.inputs, tx.dataInputs, tx.outputCandidates) - val signerTxCost = - defaultProver.signInputs(unsignedTx, from, Vector.empty, emptyStateContext, TransactionHintsBag.empty).get._2 - - val signerTxCostWithInitCost = signerTxCost + accInitCost - signerTxCostWithInitCost shouldBe txCost // signer and verifier costs should be the same - - val initialCost: Long = - tx.inputs.size * parameters.inputCost + - tx.dataInputs.size * parameters.dataInputCost + - tx.outputs.size * parameters.outputCost + - ErgoInterpreter.interpreterInitCost + - assetsCost - - txCost shouldBe (accInitCost + initialCost + inputCost(tx, from) * inputsNum) - } - } } From 2e8b71da8afd035a91f59f20f99a8a9004e81a58 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 12 Apr 2024 01:13:09 +0300 Subject: [PATCH 10/36] comments added --- .../modifiers/mempool/ErgoNodeTransactionSpec.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala index 8df6473cf1..e0b7255b90 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala @@ -13,6 +13,7 @@ import org.ergoplatform.sdk.wallet.protocol.context.TransactionContext import org.ergoplatform.settings.Parameters.MaxBlockCostIncrease import org.ergoplatform.settings.ValidationRules.{bsBlockTransactionsCost, txAssetsInOneBox} import org.ergoplatform.validation.ReplacedRule +import org.ergoplatform.validation.ValidationRules.CheckAndGetMethod import org.ergoplatform.wallet.boxes.ErgoBoxAssetExtractor import org.ergoplatform.wallet.interpreter.TransactionHintsBag import org.ergoplatform.wallet.protocol.context.InputContext @@ -717,11 +718,17 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { val activatedVersion = 3.toByte val params = new Parameters(0, LaunchParameters.parametersTable.updated(123, activatedVersion + 1), ErgoValidationSettingsUpdate.empty) - val updVs = ErgoValidationSettings.initial.updated(ErgoValidationSettingsUpdate(Seq(), Seq(1011.toShort -> ReplacedRule(1011)))) + // for next version, rule 1011 should be replaced , otherwise transaction validation will fail + // in this test, the rule is replaced with self, but for real activation this choice should be revised + val ruleId = CheckAndGetMethod.id + val updVs = ErgoValidationSettings.initial.updated(ErgoValidationSettingsUpdate(Seq(), Seq(ruleId -> ReplacedRule(ruleId)))) val stateContext = emptyStateContext.copy(currentParameters = params, validationSettings = updVs)(chainSettings) stateContext.blockVersion shouldBe activatedVersion + 1 + // the following ergo tree contains SBigInt.nbits method which is not supported by this client (as of 5.x version) + // ergo tree version is 3, less value (e.g. version = 2 which gives 1a130206022edf0580fcf622d193db060873007301) + // also works val ergoTree = DefaultSerializer.deserializeErgoTree(Base16.decode("1b130206022edf0580fcf622d193db060873007301").get) val b = new ErgoBox(1000000000L, ergoTree, Colls.emptyColl, From 1853c210a60470f2ce5e3c242e222a6721d9d2bb Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 15 Apr 2024 19:56:53 +0300 Subject: [PATCH 11/36] comments --- .../ergoplatform/settings/ErgoValidationSettings.scala | 7 ++++--- .../modifiers/mempool/ErgoNodeTransactionSpec.scala | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala index 3961e5f159..a47bc4b721 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala @@ -12,9 +12,7 @@ import scorex.util.serialization.{Reader, Writer} import scala.util.Try /** - * Ergo configuration of validation. - * - * Specifies the strategy to be used (fail-fast) and validation rules with their statuses. + * Container for validation rules along with their statuses. * Contains delta from the initial validation rules `updateFromInitial` as well as calculated current rules, * that might also be computed by applying `updateFromInitial` to `ErgoValidationSettings.initial` * @@ -29,6 +27,9 @@ case class ErgoValidationSettings(rules: Map[Short, RuleStatus], override type M = ErgoValidationSettings + /** + * In regards with consensus rules, it is worth to fail fast to avoid spam issues. + */ override val isFailFast: Boolean = true override def getError(id: Short, invalidMod: InvalidModifier): ValidationResult.Invalid = { diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala index e0b7255b90..795627ecfa 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala @@ -712,6 +712,14 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { } } + /** + * In this test we check how current version of the node (block protocol v3, at the moment of writing this test) will + * execute a script which contains a method added in next version of the protocol (namely, BIgInt.nbits), which + * is unknown to the node. + * + * As shown in the test, rule #1110 (CheckAndGetMethod) should be replaced for new methods to be passed by the node + * not recognizing it. + */ property("Soft-forked execution of Ergoscript containing unknown methods") { import ErgoTreeSerializer.DefaultSerializer From 79a6a28bbeb7e35a283f4cba0d6ff31865ae0dae Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 16 Apr 2024 16:27:16 +0300 Subject: [PATCH 12/36] checkPowForVersion2, ModQHash --- .../mining/AutolykosPowScheme.scala | 34 ++++++++++++++----- .../{NumericHash.scala => ModQHash.scala} | 2 +- .../org/ergoplatform/mining/mining.scala | 4 +-- 3 files changed, 29 insertions(+), 11 deletions(-) rename ergo-core/src/main/scala/org/ergoplatform/mining/{NumericHash.scala => ModQHash.scala} (93%) diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala index 5dd710da26..bcb14a9a96 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala @@ -97,25 +97,37 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { * Checks that `header` contains correct solution of the Autolykos PoW puzzle. */ def validate(header: Header): Try[Unit] = Try { - val b = getB(header.nBits) if (header.version == 1) { // for version 1, we check equality of left and right sides of the equation - require(checkPoWForVersion1(header, b), "Incorrect points") + require(checkPoWForVersion1(header), "Incorrect points") } else { - // for version 2, we're calculating hit and compare it with target - val hit = hitForVersion2(header) - require(hit < b, "h(f) < b condition not met") + require(checkPoWForVersion2(header), "h(f) < b condition not met") } } + /** + * Check PoW for Autolykos v2 header + * + * @param header - header to check PoW for + * @return whether PoW is valid or not + */ + def checkPoWForVersion2(header: Header): Boolean = { + val b = getB(header.nBits) + // for version 2, we're calculating hit and compare it with target + val hit = hitForVersion2(header) + hit < b + } + /** * Check PoW for Autolykos v1 header * * @param header - header to check PoW for - * @param b - PoW target * @return whether PoW is valid or not */ - def checkPoWForVersion1(header: Header, b: BigInt): Boolean = { + def checkPoWForVersion1(header: Header): Boolean = { + + val b = getB(header.nBits) // PoW target + val version = 1: Byte val msg = msgByHeader(header) @@ -177,6 +189,10 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { toBigInt(ha) } + def hitForVersion2ForMessage(msg: Array[Byte], nonce: Array[Byte]): BigInt = { + + } + /** * Pow puzzle is solved if hit < target. This function calculates the hit. * The hit is also used as "real target" in NiPoPoWs. @@ -244,7 +260,9 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { //Proving-related code which is not critical for consensus below /** - * Find a nonce from `minNonce` to `maxNonce`, such that header with the specified fields will contain + * Autolykos solver suitable for CPU-mining in testnet and devnets. + * + * Finds a nonce from `minNonce` to `maxNonce`, such that header with the specified fields will contain * correct solution of the Autolykos PoW puzzle. */ def prove(parentOpt: Option[Header], diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/NumericHash.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/ModQHash.scala similarity index 93% rename from ergo-core/src/main/scala/org/ergoplatform/mining/NumericHash.scala rename to ergo-core/src/main/scala/org/ergoplatform/mining/ModQHash.scala index 0b4beb4bd0..eae08089ff 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/NumericHash.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/ModQHash.scala @@ -13,7 +13,7 @@ import scala.annotation.tailrec * If yes, it returns the result mod q, otherwise make one more iteration using hash as an input. * This is done to ensure uniform distribution of the resulting numbers. */ -class NumericHash(val q: BigInt) extends ScorexLogging with ScorexEncoding { +class ModQHash(val q: BigInt) extends ScorexLogging with ScorexEncoding { assert(q.bigInteger.bitLength() <= 256, "We use 256 bit hash here") // biggest number <= 2^256 that is divisible by q without remainder val validRange: BigInt = (BigInt(2).pow(256) / q) * q diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala index e469225906..726ec9a808 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala @@ -19,14 +19,14 @@ package object mining { // and also to obtain target in both Autolykos v1 and v2 val q: BigInt = group.order - private val hashFn: NumericHash = new NumericHash(q) + private val modQHashFn: ModQHash = new ModQHash(q) /** * Hash function which output is in Zq. Used in Autolykos v.1 * @param in - input (bit-string) * @return - output(in Zq) */ - def hashModQ(in: Array[Byte]): BigInt = hashFn.hash(in) + def hashModQ(in: Array[Byte]): BigInt = modQHashFn.hash(in) /** * Convert byte array to unsigned integer From fc624c2e3d66baaba1daf166d16aea34a62040a5 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 16 Apr 2024 16:54:43 +0300 Subject: [PATCH 13/36] hitForVersion2ForMessage --- .../mining/AutolykosPowScheme.scala | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala index bcb14a9a96..db796e4b75 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala @@ -27,6 +27,10 @@ import scala.util.Try * Based on k-sum problem, so general idea is to find k numbers in a table of size N, such that * sum of numbers (or a hash of the sum) is less than target value. * + * There are two version of Autolykos PoW scheme, Autolykos v1 and v2. The main difference is that + * Autolykos v1 is (weakly) non-outsourceable, while v2 is outsourceable and also eliminates some vectors of + * optimizations a miner could follow. + * * See https://docs.ergoplatform.com/ErgoPow.pdf for details * * CPU Mining process is implemented in inefficient way and should not be used in real environment. @@ -164,7 +168,6 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { * @return PoW hit */ def hitForVersion2(header: Header): BigInt = { - val version = 2: Byte val msg = msgByHeader(header) val nonce = header.powSolution.n @@ -173,6 +176,25 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { val N = calcN(header) + hitForVersion2ForMessage(msg, nonce, h, N) + } + + /** + * Get a PoW hit for custom message (not necessarily a block header) with Autolykos v2. + * + * PoW then can can be checked as hit < b, where b is PoW target value + * + * @param msg - message to check PoW on + * @param nonce - PoW nonce + * @param h - for Ergo blockchain, this is height encoded as bytes. For other use-cases, could be + * unique value on each call or constant (in the latter case more pre-computations + * could be possible + * @param N - table size + * @return pow hit + */ + def hitForVersion2ForMessage(msg: Array[Byte], nonce: Array[Byte], h: Array[Byte], N: Int): BigInt = { + val version = 2: Byte // autolykos protocol version, used in genElement only + val prei8 = BigIntegers.fromUnsignedByteArray(hash(Bytes.concat(msg, nonce)).takeRight(8)) val i = BigIntegers.asUnsignedByteArray(4, prei8.mod(BigInt(N).underlying())) val f = Blake2b256(Bytes.concat(i, h, M)).drop(1) // .drop(1) is the same as takeRight(31) @@ -189,10 +211,6 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { toBigInt(ha) } - def hitForVersion2ForMessage(msg: Array[Byte], nonce: Array[Byte]): BigInt = { - - } - /** * Pow puzzle is solved if hit < target. This function calculates the hit. * The hit is also used as "real target" in NiPoPoWs. From f60e5b0db54d6e8fb2a05e1a8315a29e1d6a866c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 16 Apr 2024 23:21:13 +0300 Subject: [PATCH 14/36] close #2150: storing unparsed bytes --- .../ergoplatform/mining/AutolykosPowScheme.scala | 2 +- .../org/ergoplatform/mining/CandidateUtils.scala | 3 ++- .../ergoplatform/mining/DefaultFakePowScheme.scala | 2 +- .../modifiers/history/header/Header.scala | 10 +++++++--- .../modifiers/history/header/HeaderSerializer.scala | 13 +++++++++---- .../modifiers/history/header/HeaderWithoutPow.scala | 9 +++++---- .../modifiers/history/header/PreGenesisHeader.scala | 1 + .../network/HeaderSerializationSpecification.scala | 4 ++-- .../utils/generators/ErgoCoreGenerators.scala | 1 + .../ergoplatform/mining/CandidateGenerator.scala | 3 ++- 10 files changed, 31 insertions(+), 17 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala index 5dd710da26..58a574c02f 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala @@ -262,7 +262,7 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { val (parentId, height) = AutolykosPowScheme.derivedHeaderFields(parentOpt) val h = HeaderWithoutPow(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionHash, votes) + nBits, height, extensionHash, votes, Array.emptyByteArray) val msg = msgByHeader(h) val b = getB(nBits) val x = randomSecret() diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala index 0ad1d87624..aee8cc3fc7 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala @@ -29,7 +29,8 @@ object CandidateUtils { candidate.nBits, height, extensionRoot, - candidate.votes + candidate.votes, + Array.emptyByteArray ) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala index 732bf25805..b6a3bdeff7 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala @@ -33,7 +33,7 @@ class DefaultFakePowScheme(k: Int, n: Int) extends AutolykosPowScheme(k, n) { val d: BigInt = q / (height + 10) val s = AutolykosSolution(pk, w, n, d) Some(Header(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionHash, s, votes)) + nBits, height, extensionHash, s, votes, Array.emptyByteArray)) } override def realDifficulty(header: Header): PrivateKey = header.requiredDifficulty diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala index 092dcd219f..389d235066 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala @@ -53,8 +53,9 @@ case class Header(override val version: Header.Version, override val extensionRoot: Digest32, powSolution: AutolykosSolution, override val votes: Array[Byte], //3 bytes + override val unparsedBytes: Array[Byte], override val sizeOpt: Option[Int] = None) extends HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, votes) with PreHeader with BlockSection { + nBits, height, extensionRoot, votes, unparsedBytes) with PreHeader with BlockSection { override def serializedId: Array[Header.Version] = Algos.hash(bytes) @@ -180,7 +181,8 @@ object Header extends ApiCodecs { "size" -> h.size.asJson, "extensionId" -> Algos.encode(h.extensionId).asJson, "transactionsId" -> Algos.encode(h.transactionsId).asJson, - "adProofsId" -> Algos.encode(h.ADProofsId).asJson + "adProofsId" -> Algos.encode(h.ADProofsId).asJson, + "unparsedBytes" -> Algos.encode(h.unparsedBytes).asJson ).asJson } @@ -197,8 +199,10 @@ object Header extends ApiCodecs { version <- c.downField("version").as[Byte] votes <- c.downField("votes").as[String] solutions <- c.downField("powSolutions").as[AutolykosSolution] + unparsedBytes <- c.downField("unparsedBytes").as[Option[Array[Byte]]] } yield Header(version, parentId, adProofsRoot, stateRoot, - transactionsRoot, timestamp, nBits, height, extensionHash, solutions, Algos.decode(votes).get) + transactionsRoot, timestamp, nBits, height, extensionHash, solutions, Algos.decode(votes).get, + unparsedBytes.getOrElse(Array.emptyByteArray)) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala index b6123e1141..bbe8829a05 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala @@ -32,7 +32,8 @@ object HeaderSerializer extends ErgoSerializer[Header] { // For block version >= 2, this new byte encodes length of possible new fields. // Set to 0 for now, so no new fields. if (h.version > Header.InitialVersion) { - w.putUByte(0) + w.putUByte(h.unparsedBytes.length) + w.putBytes(h.unparsedBytes) } } @@ -56,15 +57,19 @@ object HeaderSerializer extends ErgoSerializer[Header] { // For block version >= 2, a new byte encodes length of possible new fields. // If this byte > 0, we read new fields but do nothing, as semantics of the fields is not known. - if (version > Header.InitialVersion) { + val unparsedBytes = if (version > Header.InitialVersion) { val newFieldsSize = r.getUByte() - if (newFieldsSize > 0) { + if (newFieldsSize > 0) { // todo: check protocol version? r.getBytes(newFieldsSize) + } else { + Array.emptyByteArray } + } else { + Array.emptyByteArray } HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionHash, votes) + nBits, height, extensionHash, votes, unparsedBytes) } override def parse(r: Reader): Header = { diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala index ffe10380a2..067468f2c6 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala @@ -17,19 +17,20 @@ class HeaderWithoutPow(val version: Header.Version, // 1 byte val nBits: Long, //actually it is unsigned int val height: Int, val extensionRoot: Digest32, - val votes: Array[Byte]) { //3 bytes + val votes: Array[Byte], //3 bytes + val unparsedBytes: Array[Byte]) { def toHeader(powSolution: AutolykosSolution, headerSize: Option[Int] = None): Header = Header(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, powSolution, votes, headerSize) + nBits, height, extensionRoot, powSolution, votes, unparsedBytes, headerSize) } object HeaderWithoutPow { def apply(version: Header.Version, parentId: ModifierId, ADProofsRoot: Digest32, stateRoot: ADDigest, transactionsRoot: Digest32, timestamp: Header.Timestamp, nBits: Long, height: Int, - extensionRoot: Digest32, votes: Array[Byte]): HeaderWithoutPow = { + extensionRoot: Digest32, votes: Array[Byte], unparsedBytes: Array[Byte]): HeaderWithoutPow = { new HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, votes) + nBits, height, extensionRoot, votes, unparsedBytes) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala index 7cebffbc5e..4924c63783 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala @@ -18,6 +18,7 @@ object PreGenesisHeader extends Header( extensionRoot = null, powSolution = null, votes = null, + unparsedBytes = Array.emptyByteArray, sizeOpt = None) { override def serializedId: Array[Byte] = idToBytes(Header.GenesisParentId) diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala index fb7821b255..f5445269a2 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala @@ -43,7 +43,7 @@ class HeaderSerializationSpecification extends ErgoCorePropertyTest { val votes = Array[Byte](4, 3, 0) val h = Header(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, - height, extensionRoot, powSolution, votes) + height, extensionRoot, powSolution, votes, Array.emptyByteArray) h.id shouldBe "8cf6dca6b9505243e36192fa107735024c0000cf4594b1daa2dc4e13ee86f26f" @@ -141,7 +141,7 @@ class HeaderSerializationSpecification extends ErgoCorePropertyTest { val votes = Array[Byte](0, 0, 0) val h = Header(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, - height, extensionRoot, powSolution, votes) + height, extensionRoot, powSolution, votes, Array.emptyByteArray) h.id shouldBe "f46c89e44f13a92d8409341490f97f05c85785fa8d2d2164332cc066eda95c39" diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala index 0cbb42425e..cadc6ae8b9 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala @@ -172,6 +172,7 @@ object ErgoCoreGenerators { extensionHash, powSolution, Array.fill(3)(0: Byte), + Array.emptyByteArray, None ) diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala index a42b50e6db..e7eb131d0d 100644 --- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala +++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala @@ -903,7 +903,8 @@ object CandidateGenerator extends ScorexLogging { candidate.nBits, height, extensionRoot, - candidate.votes + candidate.votes, + Array.emptyByteArray ) } From e0e6e9274a8b307b5602c9e6bdd17063f4a385f5 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 24 Apr 2024 13:34:49 +0300 Subject: [PATCH 15/36] reverting reformatting --- .../modifiers/history/header/Header.scala | 2 +- .../mempool/ErgoTransactionSpec.scala | 2 + .../mempool/ErgoNodeTransactionSpec.scala | 1016 +++++++---------- 3 files changed, 397 insertions(+), 623 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala index 092dcd219f..cb44076eb3 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala @@ -1,6 +1,6 @@ package org.ergoplatform.modifiers.history.header -import cats.syntax.either._ +import cats.syntax.either._ // needed for Scala 2.11 import sigmastate.utils.Helpers._ import io.circe.syntax._ import io.circe.{Decoder, Encoder, HCursor} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala index 2a374b09fa..dc5c26d5a7 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala @@ -83,6 +83,8 @@ class ErgoTransactionSpec extends ErgoCorePropertyTest { "{\"id\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"inputs\":[{\"boxId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"spendingProof\":{\"proofBytes\":\"\",\"extension\":{}}},{\"boxId\":\"2e9798d7eb0cd867f6dc29872f80de64c04cef10a99a58d007ef7855f0acbdb9\",\"spendingProof\":{\"proofBytes\":\"\",\"extension\":{}}}],\"dataInputs\":[{\"boxId\":\"f97d1dc4626de22db836270fe1aa004b99970791e4557de8f486f6d433b81195\"}],\"outputs\":[{\"boxId\":\"69e05b68715caaa4ca58ba59a8c8c7e031d42ad890b05f87021a28617c1e70d5\",\"value\":524940416256346,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[{\"tokenId\":\"6df03fffc9042bf0edb0d0d36d7a675239b83a9080d39716b9aa0a64cccb9963\",\"amount\":226153050},{\"tokenId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"amount\":536110126}],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":0},{\"boxId\":\"556a9a3ec7880d468e56d44e75898cf8a32f6a07344895fa6b5cf34edf101a59\",\"value\":524940416256346,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[{\"tokenId\":\"6df03fffc9042bf0edb0d0d36d7a675239b83a9080d39716b9aa0a64cccb9963\",\"amount\":226153050},{\"tokenId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"amount\":536110126}],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":1},{\"boxId\":\"16385b5b83992629909c7e004ed0421229ed3587162ce6f29b2df129472e3909\",\"value\":1016367755463674,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":2}],\"size\":329}") } + + property("context extension with neg id") { val negId: Byte = -10 diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala index 795627ecfa..b8c7b73d19 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala @@ -26,7 +26,6 @@ import sigmastate.AND import sigmastate.helpers.TestingHelpers._ import sigmastate.Values.TrueLeaf import sigmastate.interpreter.{ContextExtension, ProverResult} -import sigmastate.serialization.ErgoTreeSerializer import scala.util.{Random, Try} @@ -37,38 +36,31 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { import org.ergoplatform.utils.generators.ErgoNodeTransactionGenerators._ import org.ergoplatform.utils.generators.ErgoCoreTransactionGenerators._ - implicit private val verifier: ErgoInterpreter = ErgoInterpreter(parameters) + private implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) private val emptyModifierId: ModifierId = bytesToId(Array.fill(32)(0.toByte)) + private def checkTx(from: IndexedSeq[ErgoBox], tx: ErgoTransaction): Try[Int] = { - tx.statelessValidity() - .flatMap(_ => tx.statefulValidity(from, emptyDataBoxes, emptyStateContext)) + tx.statelessValidity().flatMap(_ => tx.statefulValidity(from, emptyDataBoxes, emptyStateContext)) } - private def modifyValue( - boxCandidate: ErgoBoxCandidate, - delta: Long - ): ErgoBoxCandidate = { + private def modifyValue(boxCandidate: ErgoBoxCandidate, delta: Long): ErgoBoxCandidate = { new ErgoBoxCandidate( boxCandidate.value + delta, boxCandidate.ergoTree, boxCandidate.creationHeight, boxCandidate.additionalTokens, - boxCandidate.additionalRegisters - ) + boxCandidate.additionalRegisters) } - private def modifyAsset( - boxCandidate: ErgoBoxCandidate, - deltaFn: Long => Long, - idToskip: TokenId - ): ErgoBoxCandidate = { + private def modifyAsset(boxCandidate: ErgoBoxCandidate, + deltaFn: Long => Long, + idToskip: TokenId): ErgoBoxCandidate = { val assetId = boxCandidate.additionalTokens.find(t => t._1 != idToskip).get._1 - val tokens = boxCandidate.additionalTokens.map { - case (id, amount) => - if (id == assetId) assetId -> deltaFn(amount) else assetId -> amount + val tokens = boxCandidate.additionalTokens.map { case (id, amount) => + if (id == assetId) assetId -> deltaFn(amount) else assetId -> amount } new ErgoBoxCandidate( @@ -76,51 +68,32 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { boxCandidate.ergoTree, boxCandidate.creationHeight, tokens, - boxCandidate.additionalRegisters - ) + boxCandidate.additionalRegisters) } - private def updateAnAsset( - tx: ErgoTransaction, - from: IndexedSeq[ErgoBox], - deltaFn: Long => Long - ) = { - val updCandidates = tx.outputCandidates - .foldLeft(IndexedSeq[ErgoBoxCandidate]() -> false) { - case ((seq, modified), ebc) => - if (modified) { - (seq :+ ebc) -> true - } else { - if (ebc.additionalTokens.nonEmpty && ebc.additionalTokens.exists(t => - !java.util.Arrays.equals(t._1.toArray, from.head.id) - )) { - (seq :+ modifyAsset(ebc, deltaFn, from.head.id.toTokenId)) -> true - } else { - (seq :+ ebc) -> false - } - } + private def updateAnAsset(tx: ErgoTransaction, from: IndexedSeq[ErgoBox], deltaFn: Long => Long) = { + val updCandidates = tx.outputCandidates.foldLeft(IndexedSeq[ErgoBoxCandidate]() -> false) { case ((seq, modified), ebc) => + if (modified) { + (seq :+ ebc) -> true + } else { + if (ebc.additionalTokens.nonEmpty && ebc.additionalTokens.exists(t => !java.util.Arrays.equals(t._1.toArray, from.head.id))) { + (seq :+ modifyAsset(ebc, deltaFn, from.head.id.toTokenId)) -> true + } else { + (seq :+ ebc) -> false + } } - ._1 + }._1 tx.copy(outputCandidates = updCandidates) } property("monotonic creation height") { def stateContext(height: Int, blockVersion: Byte): ErgoStateContext = { - val header = - defaultHeaderGen.sample.get.copy(version = blockVersion, height = height) - val params = Parameters( - LaunchParameters.height, - LaunchParameters.parametersTable.updated(Parameters.BlockVersion, blockVersion), - LaunchParameters.proposedUpdate - ) - new ErgoStateContext( - Seq(header), - None, - genesisStateDigest, - params, - ErgoValidationSettings.initial, - VotingData.empty - )(settings.chainSettings) + val header = defaultHeaderGen.sample.get.copy(version = blockVersion, height = height) + val params = Parameters(LaunchParameters.height, + LaunchParameters.parametersTable.updated(Parameters.BlockVersion, blockVersion), + LaunchParameters.proposedUpdate) + new ErgoStateContext(Seq(header), None, genesisStateDigest, params, ErgoValidationSettings.initial, + VotingData.empty)(settings.chainSettings) } def stateContextForTx(tx: ErgoTransaction, blockVersion: Byte): ErgoStateContext = { @@ -128,589 +101,388 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { } def updateOutputHeight(box: ErgoBoxCandidate, value: Int): ErgoBoxCandidate = { - new ErgoBoxCandidate( - box.value, - box.ergoTree, - value, - box.additionalTokens, - box.additionalRegisters - ) + new ErgoBoxCandidate(box.value, box.ergoTree, value, box.additionalTokens, box.additionalRegisters) } def updateInputHeight(box: ErgoBox): ErgoBox = { val creationHeight = scala.util.Random.nextInt(1000) + 1 - new ErgoBox( - box.value, - box.ergoTree, - box.additionalTokens, - box.additionalRegisters, - box.transactionId, - box.index, - creationHeight - ) + new ErgoBox(box.value, box.ergoTree, box.additionalTokens, box.additionalRegisters, + box.transactionId, box.index, creationHeight) } // retuns random transaction along with inputs, // and a boolean flag, if the latter is true, monotonic creation height rule holds, // otherwise, it does not hold - val txGen = boxesGenTemplate( - minAssets = 0, - maxAssets = 5, - minInputs = 5, - maxInputs = 10, - propositionGen = trueLeafGen - ).map { - case (boxes, _) => - boxes.map(updateInputHeight) - } - .map { boxes => - val fixed = Random.nextBoolean() - val maxHeight = boxes.map(_.creationHeight).max - val preUnsignedTx = validUnsignedTransactionFromBoxes(boxes) - val unsignedTx = if (fixed) { - preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map { - out => - val creationHeight = maxHeight + Random.nextInt(3) - updateOutputHeight(out, creationHeight) - }) - } else { - preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map { - out => - val creationHeight = maxHeight - (Random.nextInt(maxHeight) + 1) - updateOutputHeight(out, creationHeight) - }) - } - val tx = defaultProver - .sign(unsignedTx, boxes, IndexedSeq.empty, emptyStateContext) - .map(ErgoTransaction.apply) - .get - (boxes, tx, fixed) + val txGen = boxesGenTemplate(minAssets = 0, maxAssets = 5, minInputs = 5, maxInputs = 10, propositionGen = trueLeafGen).map { case (boxes, _) => + boxes.map(updateInputHeight) + }.map{ boxes => + val fixed = Random.nextBoolean() + val maxHeight = boxes.map(_.creationHeight).max + val preUnsignedTx = validUnsignedTransactionFromBoxes(boxes) + val unsignedTx = if(fixed) { + preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map{out => + val creationHeight = maxHeight + Random.nextInt(3) + updateOutputHeight(out, creationHeight) + }) + } else { + preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map{out => + val creationHeight = maxHeight - (Random.nextInt(maxHeight) + 1) + updateOutputHeight(out, creationHeight) + }) } - - forAll(txGen) { - case (boxes, tx, fixed) => - // with initial block version == 1, monotonic rule does not work - tx.statefulValidity( - boxes, - IndexedSeq.empty, - stateContextForTx(tx, blockVersion = 1) - ) - .isSuccess shouldBe true - - // with pre-5.0 block version == 2, monotonic rule does not work as well - tx.statefulValidity( - boxes, - IndexedSeq.empty, - stateContextForTx(tx, blockVersion = 2) - ) - .isSuccess shouldBe true - - // starting from block version == 3, monotonic rule works, - // so validation fails if transaction is not following the rule (fixed == false) - val ctx3 = stateContextForTx(tx, blockVersion = 3) - if (fixed) { - tx.statefulValidity(boxes, IndexedSeq.empty, ctx3).isSuccess shouldBe true - } else { - val txFailure = tx.statefulValidity(boxes, IndexedSeq.empty, ctx3) - txFailure.isSuccess shouldBe false - val cause = txFailure.toEither.left.get.getMessage - val expectedMessage = ValidationRules.errorMessage( - ValidationRules.txMonotonicHeight, - "", - emptyModifierId, - ErgoTransaction.modifierTypeId - ) - cause should startWith(expectedMessage) - } - } - } - - property("a valid transaction is valid") { - forAll(validErgoTransactionGen) { - case (from, tx) => - tx.statelessValidity().isSuccess shouldBe true - tx.statefulValidity(from, emptyDataBoxes, emptyStateContext) - .isSuccess shouldBe true - } - } - - property("ergo preservation law holds") { - forAll(validErgoTransactionGen, smallPositiveInt) { - case ((from, tx), deltaAbs) => - val delta = if (Random.nextBoolean()) -deltaAbs else deltaAbs - - val wrongTx = tx.copy(outputCandidates = - modifyValue(tx.outputCandidates.head, delta) +: tx.outputCandidates.tail - ) - - wrongTx.statelessValidity().isSuccess && - wrongTx - .statefulValidity(from, emptyDataBoxes, emptyStateContext) - .isSuccess shouldBe false - } - } - - property("impossible to create a negative-value output") { - forAll(validErgoTransactionGen) { - case (from, tx) => - val negValue = Math.min( - Math.abs(Random.nextLong()), - Long.MaxValue - tx.outputCandidates.head.value - ) - val wrongTx = tx.copy(outputCandidates = - modifyValue( - tx.outputCandidates.head, - -(tx.outputCandidates.head.value + negValue) - ) +: tx.outputCandidates.tail - ) - - wrongTx.statelessValidity().isSuccess shouldBe false - wrongTx - .statefulValidity(from, emptyDataBoxes, emptyStateContext) - .isSuccess shouldBe false - } - } - - property("impossible to overflow ergo tokens") { - forAll(validErgoTransactionGen) { - case (from, tx) => - val overflowSurplus = (Long.MaxValue - tx.outputCandidates.map(_.value).sum) + 1 - - val wrongTx = tx.copy(outputCandidates = - modifyValue(tx.outputCandidates.head, overflowSurplus) +: tx.outputCandidates.tail - ) - - wrongTx.statelessValidity().isSuccess shouldBe false - wrongTx - .statefulValidity(from, emptyDataBoxes, emptyStateContext) - .isSuccess shouldBe false - } - } - - property("assets preservation law holds") { - forAll(validErgoTransactionWithAssetsGen) { - case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ + 1)) shouldBe 'failure - } - } - - property("impossible to create an asset of negative amount") { - forAll(validErgoTransactionWithAssetsGen) { - case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ => -1)) shouldBe 'failure - } - } - - property("impossible to create an asset of zero amount") { - forAll(validErgoTransactionWithAssetsGen) { - case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ => 0)) shouldBe 'failure - } - } - - property("impossible to overflow an asset value") { - val gen = validErgoTransactionGenTemplate( - minAssets = 1, - maxAssets = 1, - maxInputs = 16, - propositionGen = trueLeafGen - ) - forAll(gen) { - case (from, tx) => - val tokenOpt = tx.outputCandidates - .flatMap(_.additionalTokens.toArray) - .groupBy(_._1) - .find(_._2.size >= 2) - - whenever(tokenOpt.nonEmpty) { - val tokenId = tokenOpt.get._1 - val tokenAmount = tokenOpt.get._2.map(_._2).sum - - var modified = false - val updCandidates = tx.outputCandidates.map { c => - val updTokens = c.additionalTokens.map { - case (id, amount) => - if (!modified && id == tokenId) { - modified = true - id -> ((Long.MaxValue - tokenAmount) + amount + 1) - } else { - id -> amount - } - } - new ErgoBoxCandidate( - c.value, - c.ergoTree, - startHeight, - updTokens, - c.additionalRegisters - ) - } - - val wrongTx = tx.copy(outputCandidates = updCandidates) - checkTx(from, wrongTx) shouldBe 'failure - } - } - } - - property("stateful validation should catch false proposition") { - val propositionGen = Gen.const(Constants.FalseLeaf) - val gen = validErgoTransactionGenTemplate(1, 1, 1, propositionGen) - forAll(gen) { - case (from, tx) => - tx.statelessValidity().isSuccess shouldBe true - val validity = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext) - validity.isSuccess shouldBe false - val e = validity.failed.get - e.getMessage should startWith( - ValidationRules.errorMessage( - ValidationRules.txScriptValidation, - "", - emptyModifierId, - ErgoTransaction.modifierTypeId - ) - ) - } - } - - property("assets usage correctly affects transaction total cost") { - val txGen = validErgoTransactionGenTemplate(1, 1, 16, propositionGen = trueLeafGen) - forAll(txGen) { - case (from, tx) => - val initTxCost = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext).get - - // already existing token from one of the inputs - val existingToken = from.flatMap(_.additionalTokens.toArray).toSet.head - // completely new token - val randomToken = - (scorex.util.Random.randomBytes().toTokenId, Random.nextInt(100000000).toLong) - - val in0 = from.last - // new token added to the last input - val modifiedIn0 = testBox( - in0.value, - in0.ergoTree, - in0.creationHeight, - in0.additionalTokens.toArray.toSeq :+ randomToken, - in0.additionalRegisters, - in0.transactionId, - in0.index - ) - val txInMod0 = tx.inputs.last.copy(boxId = modifiedIn0.id) - - val in1 = from.last - // existing token added to the last input - val modifiedIn1 = testBox( - in1.value, - in1.ergoTree, - in1.creationHeight, - in1.additionalTokens.toArray.toSeq :+ existingToken, - in1.additionalRegisters, - in1.transactionId, - in1.index - ) - val txInMod1 = tx.inputs.last.copy(boxId = modifiedIn1.id) - - val out0 = tx.outputs.last - // new token added to the last output - val modifiedOut0 = testBox( - out0.value, - out0.ergoTree, - out0.creationHeight, - out0.additionalTokens.toArray.toSeq :+ randomToken, - out0.additionalRegisters, - out0.transactionId, - out0.index - ) - // existing token added to the last output - val modifiedOut1 = testBox( - out0.value, - out0.ergoTree, - out0.creationHeight, - out0.additionalTokens.toArray.toSeq :+ existingToken, - out0.additionalRegisters, - out0.transactionId, - out0.index - ) - - // update transaction inputs and outputs accordingly - val txMod0 = tx.copy(inputs = tx.inputs.init :+ txInMod0) // new token group added to one input - val txMod1 = tx.copy(inputs = tx.inputs.init :+ txInMod1) // existing token added to one input - val txMod2 = tx.copy( - inputs = tx.inputs.init :+ txInMod0, // new token group added to one input and one output - outputCandidates = tx.outputCandidates.init :+ modifiedOut0 - ) - val txMod3 = tx.copy( - inputs = tx.inputs.init :+ txInMod1, // existing token added to one input and one output - outputCandidates = tx.outputCandidates.init :+ modifiedOut1 - ) - - val inputIncTxCost0 = txMod0 - .statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext) - .get - val inputIncTxCost1 = txMod1 - .statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext) - .get - val outputIncTxCost0 = txMod2 - .statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext) - .get - val outputIncTxCost1 = txMod3 - .statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext) - .get - - (inputIncTxCost0 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault * 2 // one more group + one more token in total - (inputIncTxCost1 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault // one more token in total - (outputIncTxCost0 - inputIncTxCost0) shouldEqual Parameters.TokenAccessCostDefault * 2 - (outputIncTxCost1 - inputIncTxCost1) shouldEqual Parameters.TokenAccessCostDefault + val tx = defaultProver.sign(unsignedTx, boxes, IndexedSeq.empty, emptyStateContext) + .map(ErgoTransaction.apply) + .get + (boxes, tx, fixed) } - } - property( - "spam simulation (transaction validation cost with too many tokens exceeds block limit)" - ) { - val bxsQty = 392 // with greater value test is failing with collection size exception - val (inputs, tx) = validErgoTransactionGenTemplate(1, 1, 16).sample.get // it takes too long to test with `forAll` - val tokens = - (0 until 255).map(_ => (scorex.util.Random.randomBytes().toTokenId, Random.nextLong) - ) - val (in, out) = { - val in0 = inputs.head - val out0 = tx.outputs.head - val inputsMod = (0 until bxsQty).map { i => - testBox( - 10000000000L, - in0.ergoTree, - in0.creationHeight, - tokens, - in0.additionalRegisters, - in0.transactionId, - i.toShort - ) - } - val outputsMod = (0 until bxsQty).map { i => - testBox( - 10000000000L, - out0.ergoTree, - out0.creationHeight, - tokens, - out0.additionalRegisters, - out0.transactionId, - i.toShort - ) + forAll(txGen){ case (boxes, tx, fixed) => + // with initial block version == 1, monotonic rule does not work + tx.statefulValidity(boxes, IndexedSeq.empty, stateContextForTx(tx, blockVersion = 1)).isSuccess shouldBe true + + // with pre-5.0 block version == 2, monotonic rule does not work as well + tx.statefulValidity(boxes, IndexedSeq.empty, stateContextForTx(tx, blockVersion = 2)).isSuccess shouldBe true + + // starting from block version == 3, monotonic rule works, + // so validation fails if transaction is not following the rule (fixed == false) + val ctx3 = stateContextForTx(tx, blockVersion = 3) + if (fixed) { + tx.statefulValidity(boxes, IndexedSeq.empty, ctx3).isSuccess shouldBe true + } else { + val txFailure = tx.statefulValidity(boxes, IndexedSeq.empty, ctx3) + txFailure.isSuccess shouldBe false + val cause = txFailure.toEither.left.get.getMessage + val expectedMessage = ValidationRules.errorMessage(ValidationRules.txMonotonicHeight, "", emptyModifierId, ErgoTransaction.modifierTypeId) + cause should startWith(expectedMessage) } - inputsMod -> outputsMod - } - val inputsPointers = { - val inSample = tx.inputs.head - (0 until bxsQty).map(i => inSample.copy(boxId = in(i).id)) - } - val txMod = tx.copy(inputs = inputsPointers, outputCandidates = out) - val validFailure = txMod.statefulValidity(in, emptyDataBoxes, emptyStateContext) - validFailure.failed.get.getMessage should startWith( - ValidationRules - .errorMessage( - txAssetsInOneBox, - "", - emptyModifierId, - ErgoTransaction.modifierTypeId - ) - .take(30) - ) - } - - property("transaction with too many inputs should be rejected") { - - //we assume that verifier must finish verification of any script in less time than 250K hash calculations - // (for the Blake2b256 hash function over a single block input) - val Timeout: Long = { - val hf = Blake2b256 - - //just in case to heat up JVM - (1 to 5000000).foreach(i => hf(s"$i-$i")) - - val t0 = System.currentTimeMillis() - (1 to 250000).foreach(i => hf(s"$i")) - val t = System.currentTimeMillis() - t - t0 } - - val gen = validErgoTransactionGenTemplate(0, 0, 2000, trueLeafGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - //check that spam transaction is being rejected quickly - implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) - val (validity, time0) = BenchmarkUtil.measureTime( - tx.statefulValidity(from, IndexedSeq(), emptyStateContext) - ) - validity.isSuccess shouldBe false - assert(time0 <= Timeout) - - val cause = validity.failed.get.getMessage - cause should startWith( - ValidationRules - .errorMessage( - bsBlockTransactionsCost, - "", - emptyModifierId, - ErgoTransaction.modifierTypeId - ) - .take(30) - ) - - //check that spam transaction validation with no cost limit is indeed taking too much time - import Parameters._ - val maxCost = (Int.MaxValue - 10) / 10 // cannot use Int.MaxValue directly due to overflow when it is converted to block cost - val ps = Parameters( - 0, - DefaultParameters.updated(MaxBlockCostIncrease, maxCost), - emptyVSUpdate - ) - val sc = new ErgoStateContext( - Seq.empty, - None, - genesisStateDigest, - ps, - ErgoValidationSettings.initial, - VotingData.empty - )(settings.chainSettings) - .upcoming( - org.ergoplatform.mining.group.generator, - 0L, - settings.chainSettings.initialNBits, - Array.fill(3)(0.toByte), - ErgoValidationSettingsUpdate.empty, - 0.toByte - ) - val (_, time) = BenchmarkUtil.measureTime( - tx.statefulValidity(from, IndexedSeq(), sc)(verifier) - ) - - assert(time > Timeout) - } - - property("transaction cost") { - def paramsWith(manualCost: Int) = Parameters( - 0, - Parameters.DefaultParameters + (MaxBlockCostIncrease -> manualCost), - ErgoValidationSettingsUpdate.empty - ) - - val gen = validErgoTransactionGenTemplate(0, 0, 10, trueLeafGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - // calculate costs manually - val initialCost: Long = - tx.inputs.size * parameters.inputCost + - tx.dataInputs.size * parameters.dataInputCost + - tx.outputs.size * parameters.outputCost + - ErgoInterpreter.interpreterInitCost - val (outAssets, outAssetsNum) = tx.outAssetsTry.get - val (inAssets, inAssetsNum) = ErgoBoxAssetExtractor.extractAssets(from).get - val totalAssetsAccessCost = - (outAssetsNum + inAssetsNum) * parameters.tokenAccessCost + - (inAssets.size + outAssets.size) * parameters.tokenAccessCost - val scriptsValidationCosts = tx.inputs.size + 1 // +1 for the block to JIT cost scaling - println(s"tx.inputs.size: ${tx.inputs.size}") - println( - s"initialCost + totalAssetsAccessCost: ${initialCost + totalAssetsAccessCost}" - ) - val approxCost: Int = - (initialCost + totalAssetsAccessCost + scriptsValidationCosts).toInt - - // check that validation pass if cost limit equals to approximated cost - val sc = stateContextWith(paramsWith(approxCost)) - sc.currentParameters.maxBlockCost shouldBe approxCost - val calculatedCost = tx - .statefulValidity(from, IndexedSeq(), sc)(ErgoInterpreter(sc.currentParameters)) - .get - approxCost - calculatedCost <= 1 shouldBe true - - // transaction exceeds computations limit - val sc2 = stateContextWith(paramsWith(approxCost - 1)) - tx.statefulValidity(from, IndexedSeq(), sc2)(ErgoInterpreter(sc2.currentParameters)) shouldBe 'failure - - // transaction exceeds computations limit due to non-zero accumulatedCost - tx.statefulValidity(from, IndexedSeq(), sc, accumulatedCost = 1)( - ErgoInterpreter(sc.currentParameters) - ) shouldBe 'failure } - property("cost accumulated correctly across inputs") { - val accInitCost = 100000 + property("a valid transaction is valid") { + forAll(validErgoTransactionGen) { case (from, tx) => + tx.statelessValidity().isSuccess shouldBe true + tx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe true + } + } + + property("ergo preservation law holds") { + forAll(validErgoTransactionGen, smallPositiveInt) { case ((from, tx), deltaAbs) => + val delta = if (Random.nextBoolean()) -deltaAbs else deltaAbs + + val wrongTx = tx.copy(outputCandidates = + modifyValue(tx.outputCandidates.head, delta) +: tx.outputCandidates.tail) + + wrongTx.statelessValidity().isSuccess && + wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false + } + } + + property("impossible to create a negative-value output") { + forAll(validErgoTransactionGen) { case (from, tx) => + val negValue = Math.min(Math.abs(Random.nextLong()), Long.MaxValue - tx.outputCandidates.head.value) + val wrongTx = tx.copy(outputCandidates = + modifyValue(tx.outputCandidates.head, -(tx.outputCandidates.head.value + negValue)) +: tx.outputCandidates.tail) + + wrongTx.statelessValidity().isSuccess shouldBe false + wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false + } + } + + property("impossible to overflow ergo tokens") { + forAll(validErgoTransactionGen) { case (from, tx) => + val overflowSurplus = (Long.MaxValue - tx.outputCandidates.map(_.value).sum) + 1 + + val wrongTx = tx.copy(outputCandidates = + modifyValue(tx.outputCandidates.head, overflowSurplus) +: tx.outputCandidates.tail) + + wrongTx.statelessValidity().isSuccess shouldBe false + wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false + } + } + + property("assets preservation law holds") { + forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => + checkTx(from, updateAnAsset(tx, from, _ + 1)) shouldBe 'failure + } + } + + property("impossible to create an asset of negative amount") { + forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => + checkTx(from, updateAnAsset(tx, from, _ => -1)) shouldBe 'failure + } + } + + property("impossible to create an asset of zero amount") { + forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => + checkTx(from, updateAnAsset(tx, from, _ => 0)) shouldBe 'failure + } + } + + property("impossible to overflow an asset value") { + val gen = validErgoTransactionGenTemplate(minAssets = 1, maxAssets = 1, maxInputs = 16, propositionGen = trueLeafGen) + forAll(gen) { case (from, tx) => + val tokenOpt = tx.outputCandidates.flatMap(_.additionalTokens.toArray) + .groupBy(_._1).find(_._2.size >= 2) + + whenever(tokenOpt.nonEmpty) { + val tokenId = tokenOpt.get._1 + val tokenAmount = tokenOpt.get._2.map(_._2).sum + + var modified = false + val updCandidates = tx.outputCandidates.map { c => + val updTokens = c.additionalTokens.map { case (id, amount) => + if (!modified && id == tokenId) { + modified = true + id -> ((Long.MaxValue - tokenAmount) + amount + 1) + } else { + id -> amount + } + } + new ErgoBoxCandidate(c.value, c.ergoTree, startHeight, updTokens, c.additionalRegisters) + } + + val wrongTx = tx.copy(outputCandidates = updCandidates) + checkTx(from, wrongTx) shouldBe 'failure + } + } + } + + property("stateful validation should catch false proposition") { + val propositionGen = Gen.const(Constants.FalseLeaf) + val gen = validErgoTransactionGenTemplate(1, 1, 1, propositionGen) + forAll(gen) { case (from, tx) => + tx.statelessValidity().isSuccess shouldBe true + val validity = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext) + validity.isSuccess shouldBe false + val e = validity.failed.get + e.getMessage should startWith(ValidationRules.errorMessage(ValidationRules.txScriptValidation, "", emptyModifierId, ErgoTransaction.modifierTypeId)) + } + } + + property("assets usage correctly affects transaction total cost") { + val txGen = validErgoTransactionGenTemplate(1, 1,16, propositionGen = trueLeafGen) + forAll(txGen) { case (from, tx) => + val initTxCost = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext).get + + // already existing token from one of the inputs + val existingToken = from.flatMap(_.additionalTokens.toArray).toSet.head + // completely new token + val randomToken = (scorex.util.Random.randomBytes().toTokenId, Random.nextInt(100000000).toLong) + + val in0 = from.last + // new token added to the last input + val modifiedIn0 = testBox(in0.value, in0.ergoTree, in0.creationHeight, + in0.additionalTokens.toArray.toSeq :+ randomToken, in0.additionalRegisters, in0.transactionId, in0.index) + val txInMod0 = tx.inputs.last.copy(boxId = modifiedIn0.id) + + val in1 = from.last + // existing token added to the last input + val modifiedIn1 = testBox(in1.value, in1.ergoTree, in1.creationHeight, + in1.additionalTokens.toArray.toSeq :+ existingToken, in1.additionalRegisters, in1.transactionId, in1.index) + val txInMod1 = tx.inputs.last.copy(boxId = modifiedIn1.id) + + val out0 = tx.outputs.last + // new token added to the last output + val modifiedOut0 = testBox(out0.value, out0.ergoTree, out0.creationHeight, + out0.additionalTokens.toArray.toSeq :+ randomToken, out0.additionalRegisters, out0.transactionId, out0.index) + // existing token added to the last output + val modifiedOut1 = testBox(out0.value, out0.ergoTree, out0.creationHeight, + out0.additionalTokens.toArray.toSeq :+ existingToken, out0.additionalRegisters, out0.transactionId, out0.index) + + // update transaction inputs and outputs accordingly + val txMod0 = tx.copy(inputs = tx.inputs.init :+ txInMod0) // new token group added to one input + val txMod1 = tx.copy(inputs = tx.inputs.init :+ txInMod1) // existing token added to one input + val txMod2 = tx.copy(inputs = tx.inputs.init :+ txInMod0, // new token group added to one input and one output + outputCandidates = tx.outputCandidates.init :+ modifiedOut0) + val txMod3 = tx.copy(inputs = tx.inputs.init :+ txInMod1, // existing token added to one input and one output + outputCandidates = tx.outputCandidates.init :+ modifiedOut1) + + val inputIncTxCost0 = txMod0.statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext).get + val inputIncTxCost1 = txMod1.statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext).get + val outputIncTxCost0 = txMod2.statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext).get + val outputIncTxCost1 = txMod3.statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext).get + + (inputIncTxCost0 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault * 2 // one more group + one more token in total + (inputIncTxCost1 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault // one more token in total + (outputIncTxCost0 - inputIncTxCost0) shouldEqual Parameters.TokenAccessCostDefault * 2 + (outputIncTxCost1 - inputIncTxCost1) shouldEqual Parameters.TokenAccessCostDefault + } + } + + property("spam simulation (transaction validation cost with too many tokens exceeds block limit)") { + val bxsQty = 392 // with greater value test is failing with collection size exception + val (inputs, tx) = validErgoTransactionGenTemplate(1, 1,16).sample.get // it takes too long to test with `forAll` + val tokens = (0 until 255).map(_ => (scorex.util.Random.randomBytes().toTokenId, Random.nextLong)) + val (in, out) = { + val in0 = inputs.head + val out0 = tx.outputs.head + val inputsMod = (0 until bxsQty).map { i => + testBox(10000000000L, in0.ergoTree, in0.creationHeight, + tokens, in0.additionalRegisters, in0.transactionId, i.toShort) + } + val outputsMod = (0 until bxsQty).map { i => + testBox(10000000000L, out0.ergoTree, out0.creationHeight, + tokens, out0.additionalRegisters, out0.transactionId, i.toShort) + } + inputsMod -> outputsMod + } + val inputsPointers = { + val inSample = tx.inputs.head + (0 until bxsQty).map(i => inSample.copy(boxId = in(i).id)) + } + val txMod = tx.copy(inputs = inputsPointers, outputCandidates = out) + val validFailure = txMod.statefulValidity(in, emptyDataBoxes, emptyStateContext) + validFailure.failed.get.getMessage should startWith(ValidationRules.errorMessage(txAssetsInOneBox, "", emptyModifierId, ErgoTransaction.modifierTypeId).take(30)) + } + + property("transaction with too many inputs should be rejected") { + + //we assume that verifier must finish verification of any script in less time than 250K hash calculations + // (for the Blake2b256 hash function over a single block input) + val Timeout: Long = { + val hf = Blake2b256 + + //just in case to heat up JVM + (1 to 5000000).foreach(i => hf(s"$i-$i")) + + val t0 = System.currentTimeMillis() + (1 to 250000).foreach(i => hf(s"$i")) + val t = System.currentTimeMillis() + t - t0 + } + + val gen = validErgoTransactionGenTemplate(0, 0, 2000, trueLeafGen) + val (from, tx) = gen.sample.get + tx.statelessValidity().isSuccess shouldBe true + + //check that spam transaction is being rejected quickly + implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) + val (validity, time0) = BenchmarkUtil.measureTime(tx.statefulValidity(from, IndexedSeq(), emptyStateContext)) + validity.isSuccess shouldBe false + assert(time0 <= Timeout) + + val cause = validity.failed.get.getMessage + cause should startWith(ValidationRules.errorMessage(bsBlockTransactionsCost, "", emptyModifierId, ErgoTransaction.modifierTypeId).take(30)) + + //check that spam transaction validation with no cost limit is indeed taking too much time + import Parameters._ + val maxCost = (Int.MaxValue - 10) / 10 // cannot use Int.MaxValue directly due to overflow when it is converted to block cost + val ps = Parameters(0, DefaultParameters.updated(MaxBlockCostIncrease, maxCost), emptyVSUpdate) + val sc = new ErgoStateContext(Seq.empty, None, genesisStateDigest, ps, ErgoValidationSettings.initial, + VotingData.empty)(settings.chainSettings) + .upcoming(org.ergoplatform.mining.group.generator, + 0L, + settings.chainSettings.initialNBits, + Array.fill(3)(0.toByte), + ErgoValidationSettingsUpdate.empty, + 0.toByte) + val (_, time) = BenchmarkUtil.measureTime( + tx.statefulValidity(from, IndexedSeq(), sc)(verifier) + ) + + assert(time > Timeout) + } + + property("transaction cost") { + def paramsWith(manualCost: Int) = Parameters( + 0, + Parameters.DefaultParameters + (MaxBlockCostIncrease -> manualCost), + ErgoValidationSettingsUpdate.empty + ) + + val gen = validErgoTransactionGenTemplate(0, 0,10, trueLeafGen) + val (from, tx) = gen.sample.get + tx.statelessValidity().isSuccess shouldBe true + + // calculate costs manually + val initialCost: Long = + tx.inputs.size * parameters.inputCost + + tx.dataInputs.size * parameters.dataInputCost + + tx.outputs.size * parameters.outputCost + + ErgoInterpreter.interpreterInitCost + val (outAssets, outAssetsNum) = tx.outAssetsTry.get + val (inAssets, inAssetsNum) = ErgoBoxAssetExtractor.extractAssets(from).get + val totalAssetsAccessCost = + (outAssetsNum + inAssetsNum) * parameters.tokenAccessCost + + (inAssets.size + outAssets.size) * parameters.tokenAccessCost + val scriptsValidationCosts = tx.inputs.size + 1 // +1 for the block to JIT cost scaling + println(s"tx.inputs.size: ${tx.inputs.size}") + println(s"initialCost + totalAssetsAccessCost: ${initialCost + totalAssetsAccessCost}") + val approxCost: Int = (initialCost + totalAssetsAccessCost + scriptsValidationCosts).toInt + + + // check that validation pass if cost limit equals to approximated cost + val sc = stateContextWith(paramsWith(approxCost)) + sc.currentParameters.maxBlockCost shouldBe approxCost + val calculatedCost = tx.statefulValidity(from, IndexedSeq(), sc)(ErgoInterpreter(sc.currentParameters)).get + approxCost - calculatedCost <= 1 shouldBe true + + // transaction exceeds computations limit + val sc2 = stateContextWith(paramsWith(approxCost - 1)) + tx.statefulValidity(from, IndexedSeq(), sc2)(ErgoInterpreter(sc2.currentParameters)) shouldBe 'failure + + // transaction exceeds computations limit due to non-zero accumulatedCost + tx.statefulValidity(from, IndexedSeq(), sc, accumulatedCost = 1)(ErgoInterpreter(sc.currentParameters)) shouldBe 'failure + } + + property("cost accumulated correctly across inputs") { + val accInitCost = 100000 + + def inputCost(tx: ErgoTransaction, from: IndexedSeq[ErgoBox]): Long = { + val idx = 0 + val input = tx.inputs(idx) + val proof = input.spendingProof + val transactionContext = TransactionContext(from, IndexedSeq(), tx) + val inputContext = InputContext(idx.toShort, proof.extension) + + val ctx = new ErgoContext( + emptyStateContext, transactionContext, inputContext, + costLimit = emptyStateContext.currentParameters.maxBlockCost, + initCost = 0) + + val messageToSign = tx.messageToSign + + val inputCost = verifier.verify(from(idx).ergoTree, ctx, proof, messageToSign).get._2 + + inputCost + } + + forAll(smallPositiveInt) { inputsNum => + + val nonTrivialTrueGen = Gen.const(AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp.treeWithSegregation) + val gen = validErgoTransactionGenTemplate(0, 0, inputsNum, nonTrivialTrueGen) + val (from, tx) = gen.sample.get + tx.statelessValidity().isSuccess shouldBe true + + tx.inputs.length shouldBe inputsNum + + val tokenAccessCost = emptyStateContext.currentParameters.tokenAccessCost + + val txCost = tx.statefulValidity(from, IndexedSeq(), emptyStateContext, accInitCost).get + + val (inAssets, inAssetsNum): (Map[Seq[Byte], Long], Int) = ErgoBoxAssetExtractor.extractAssets(from).get + val (outAssets, outAssetsNum): (Map[Seq[Byte], Long], Int) = ErgoBoxAssetExtractor.extractAssets(tx.outputs).get + + val assetsCost = inAssetsNum * tokenAccessCost + inAssets.size * tokenAccessCost + + outAssetsNum * tokenAccessCost + outAssets.size * tokenAccessCost + + val unsignedTx = UnsignedErgoTransaction(tx.inputs, tx.dataInputs, tx.outputCandidates) + val signerTxCost = + defaultProver.signInputs(unsignedTx, from, Vector.empty, emptyStateContext, TransactionHintsBag.empty).get._2 + + val signerTxCostWithInitCost = signerTxCost + accInitCost + signerTxCostWithInitCost shouldBe txCost // signer and verifier costs should be the same + + val initialCost: Long = + tx.inputs.size * parameters.inputCost + + tx.dataInputs.size * parameters.dataInputCost + + tx.outputs.size * parameters.outputCost + + ErgoInterpreter.interpreterInitCost + + assetsCost - def inputCost(tx: ErgoTransaction, from: IndexedSeq[ErgoBox]): Long = { - val idx = 0 - val input = tx.inputs(idx) - val proof = input.spendingProof - val transactionContext = TransactionContext(from, IndexedSeq(), tx) - val inputContext = InputContext(idx.toShort, proof.extension) - - val ctx = new ErgoContext( - emptyStateContext, - transactionContext, - inputContext, - costLimit = emptyStateContext.currentParameters.maxBlockCost, - initCost = 0 - ) - - val messageToSign = tx.messageToSign - - val inputCost = - verifier.verify(from(idx).ergoTree, ctx, proof, messageToSign).get._2 - - inputCost - } - - forAll(smallPositiveInt) { inputsNum => - val nonTrivialTrueGen = - Gen.const(AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp.treeWithSegregation) - val gen = validErgoTransactionGenTemplate(0, 0, inputsNum, nonTrivialTrueGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - tx.inputs.length shouldBe inputsNum - - val tokenAccessCost = emptyStateContext.currentParameters.tokenAccessCost - - val txCost = - tx.statefulValidity(from, IndexedSeq(), emptyStateContext, accInitCost).get - - val (inAssets, inAssetsNum): (Map[Seq[Byte], Long], Int) = - ErgoBoxAssetExtractor.extractAssets(from).get - val (outAssets, outAssetsNum): (Map[Seq[Byte], Long], Int) = - ErgoBoxAssetExtractor.extractAssets(tx.outputs).get - - val assetsCost = inAssetsNum * tokenAccessCost + inAssets.size * tokenAccessCost + - outAssetsNum * tokenAccessCost + outAssets.size * tokenAccessCost - - val unsignedTx = - UnsignedErgoTransaction(tx.inputs, tx.dataInputs, tx.outputCandidates) - val signerTxCost = - defaultProver - .signInputs( - unsignedTx, - from, - Vector.empty, - emptyStateContext, - TransactionHintsBag.empty - ) - .get - ._2 - - val signerTxCostWithInitCost = signerTxCost + accInitCost - signerTxCostWithInitCost shouldBe txCost // signer and verifier costs should be the same - - val initialCost: Long = - tx.inputs.size * parameters.inputCost + - tx.dataInputs.size * parameters.dataInputCost + - tx.outputs.size * parameters.outputCost + - ErgoInterpreter.interpreterInitCost + - assetsCost - - txCost shouldBe (accInitCost + initialCost + inputCost(tx, from) * inputsNum) - } - } + txCost shouldBe (accInitCost + initialCost + inputCost(tx, from) * inputsNum) + } + } /** * In this test we check how current version of the node (block protocol v3, at the moment of writing this test) will @@ -721,7 +493,7 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { * not recognizing it. */ property("Soft-forked execution of Ergoscript containing unknown methods") { - import ErgoTreeSerializer.DefaultSerializer + import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer val activatedVersion = 3.toByte val params = new Parameters(0, LaunchParameters.parametersTable.updated(123, activatedVersion + 1), ErgoValidationSettingsUpdate.empty) From dc74081c9a75309b232c56b470d1e9f290721797 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 24 Apr 2024 13:51:43 +0300 Subject: [PATCH 16/36] ModQHash remark --- ergo-core/src/main/scala/org/ergoplatform/mining/ModQHash.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/ModQHash.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/ModQHash.scala index eae08089ff..1d4f360332 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/ModQHash.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/ModQHash.scala @@ -12,6 +12,8 @@ import scala.annotation.tailrec * in range from 0 to a maximum number divisible by q without remainder. * If yes, it returns the result mod q, otherwise make one more iteration using hash as an input. * This is done to ensure uniform distribution of the resulting numbers. + * + * Used in Autolykos v1 only! */ class ModQHash(val q: BigInt) extends ScorexLogging with ScorexEncoding { assert(q.bigInteger.bitLength() <= 256, "We use 256 bit hash here") From 21a6c7c6eb928e3c97c7414445b6aca8d3280bbe Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 24 Apr 2024 14:30:31 +0300 Subject: [PATCH 17/36] accounting for new header bytes only since version 5 of the protocol, new Header structure field description --- .../org/ergoplatform/modifiers/history/header/Header.scala | 6 ++++++ .../modifiers/history/header/HeaderSerializer.scala | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala index 389d235066..4a741851a5 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala @@ -40,6 +40,7 @@ import scala.concurrent.duration.FiniteDuration * @param extensionRoot - Merkle tree digest of the extension section of the block * @param powSolution - solution for the proof-of-work puzzle * @param votes - votes for changing system parameters + * @param unparsedBytes - bytes of fields added in future versions of the protocol and not parseable * @param sizeOpt - optionally, size of the header (to avoid serialization on calling .length) */ case class Header(override val version: Header.Version, @@ -139,6 +140,11 @@ object Header extends ApiCodecs { */ val Interpreter50Version: Byte = 3 + /** + * Block version after the 6.0 soft-fork + * 6.0 interpreter (EIP-50) + */ + val Interpreter60Version: Byte = 4 def toSigma(header: Header): sigma.Header = CHeader( diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala index bbe8829a05..d6d72f1aa4 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala @@ -59,7 +59,8 @@ object HeaderSerializer extends ErgoSerializer[Header] { // If this byte > 0, we read new fields but do nothing, as semantics of the fields is not known. val unparsedBytes = if (version > Header.InitialVersion) { val newFieldsSize = r.getUByte() - if (newFieldsSize > 0) { // todo: check protocol version? + if (newFieldsSize > 0 && version > Header.Interpreter60Version) { + // new bytes could be added only for block version >= 5 r.getBytes(newFieldsSize) } else { Array.emptyByteArray From 440126e1aaa8f9bea647ae77a4fbb6e9383e8edf Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 24 Apr 2024 18:16:56 +0300 Subject: [PATCH 18/36] improved comment for NIncreasementHeightMax --- .../scala/org/ergoplatform/mining/AutolykosPowScheme.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala index db796e4b75..d355b8d898 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala @@ -62,7 +62,8 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { val IncreasePeriodForN: Height = 50 * 1024 /** - * On this height, the table (`N` value) will stop to grow + * On this height, the table (`N` value) will stop to grow. + * Max N on and after this height would be 2,143,944,600 which is still less than 2^^31. */ val NIncreasementHeightMax: Height = 4198400 From dac737e7591de3704b934f7411b08398861f7709 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 2 May 2024 15:49:07 +0300 Subject: [PATCH 19/36] i2155 --- .../nodeView/ErgoNodeViewHolder.scala | 2 +- .../nodeView/mempool/ErgoMemPool.scala | 29 +++++++++++--- .../nodeView/mempool/ErgoMemPoolSpec.scala | 38 +++++++++++++++++-- .../mempool/MempoolTransactionsTest.scala | 4 +- 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/ErgoNodeViewHolder.scala b/src/main/scala/org/ergoplatform/nodeView/ErgoNodeViewHolder.scala index e68b9d4693..19af8bba61 100644 --- a/src/main/scala/org/ergoplatform/nodeView/ErgoNodeViewHolder.scala +++ b/src/main/scala/org/ergoplatform/nodeView/ErgoNodeViewHolder.scala @@ -402,7 +402,7 @@ abstract class ErgoNodeViewHolder[State <: ErgoState[State]](settings: ErgoSetti .flatMap(extractTransactions) .filter(tx => !appliedTxs.exists(_.id == tx.id)) .map(tx => UnconfirmedTransaction(tx, None)) - memPool.remove(appliedTxs).put(rolledBackTxs) + memPool.removeWithDoubleSpends(appliedTxs).put(rolledBackTxs) } /** diff --git a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala index df08cd4858..76f2d543d1 100644 --- a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala +++ b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala @@ -108,13 +108,32 @@ class ErgoMemPool private[mempool](private[mempool] val pool: OrderedTxPool, /** * Remove transaction from the pool */ - def remove(tx: ErgoTransaction): ErgoMemPool = { - log.debug(s"Removing transaction ${tx.id} from the mempool") - new ErgoMemPool(pool.remove(tx), updateStatsOnRemoval(tx), sortingOption) + def removeTxAndDoubleSpends(tx: ErgoTransaction): ErgoMemPool = { + def removeTx(mp: ErgoMemPool, tx: ErgoTransaction): ErgoMemPool = { + log.debug(s"Removing transaction ${tx.id} from the mempool") + new ErgoMemPool(mp.pool.remove(tx), mp.updateStatsOnRemoval(tx), sortingOption) + } + + val poolWithoutTx = removeTx(this, tx) + val doubleSpentTransactionIds = tx.inputs.flatMap(i => + poolWithoutTx.pool.inputs.get(i.boxId) + ).toSet + val doubleSpentTransactions = doubleSpentTransactionIds.flatMap { txId => + poolWithoutTx.pool.orderedTransactions.get(txId) + } + doubleSpentTransactions.foldLeft(poolWithoutTx) { case (pool, tx) => + removeTx(pool, tx.transaction) + } } - def remove(txs: TraversableOnce[ErgoTransaction]): ErgoMemPool = { - txs.foldLeft(this) { case (acc, tx) => acc.remove(tx) } + def removeWithDoubleSpends(txs: TraversableOnce[ErgoTransaction]): ErgoMemPool = { + txs.foldLeft(this) { case (memPool, tx) => + if (memPool.contains(tx.id)) { + memPool.removeTxAndDoubleSpends(tx) + } else { + memPool + } + } } /** diff --git a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala index 5ee89a9a4c..486c626803 100644 --- a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala @@ -1,11 +1,11 @@ package org.ergoplatform.nodeView.mempool import org.ergoplatform.{ErgoBoxCandidate, Input} -import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.{SortingOption, ProcessingOutcome} +import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.{ProcessingOutcome, SortingOption} import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.ErgoTestHelpers +import org.ergoplatform.utils.{ErgoTestHelpers, RandomWrapper} import org.scalatest.flatspec.AnyFlatSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import sigmastate.Values.{ByteArrayConstant, TrueLeaf} @@ -297,11 +297,41 @@ class ErgoMemPoolSpec extends AnyFlatSpec } pool.size shouldBe (family_depth + 1) * txs.size allTxs.foreach { tx => - pool = pool.remove(tx.transaction) + pool = pool.removeTxAndDoubleSpends(tx.transaction) } pool.size shouldBe 0 } + it should "correctly remove doublespents of a transaction from pool" in { + val (us, bh) = createUtxoState(settings) + val genesis = validFullBlock(None, us, bh) + val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get + val boxes = wus.takeBoxes(4) + + val limit = 10000 + + val tx1 = validTransactionsFromBoxes(limit, boxes.take(1), new RandomWrapper) + ._1.map(tx => UnconfirmedTransaction(tx, None)).head + + val tx2 = validTransactionsFromBoxes(limit, boxes.takeRight(2), new RandomWrapper) + ._1.map(tx => UnconfirmedTransaction(tx, None)).head + + val tx3 = validTransactionsFromBoxes(limit, boxes.take(1), new RandomWrapper) + ._1.map(tx => UnconfirmedTransaction(tx, None)).head + + tx1.transaction.inputs.head.boxId shouldBe tx3.transaction.inputs.head.boxId + + var pool = ErgoMemPool.empty(settings) + Seq(tx2, tx3).foreach { tx => + pool = pool.put(tx) + } + + pool = pool.removeTxAndDoubleSpends(tx1.transaction) + pool.contains(tx1.transaction) shouldBe false + pool.contains(tx2.transaction) shouldBe true + pool.contains(tx3.transaction) shouldBe false + } + it should "return results take / getAll / getAllPrioritized sorted by priority" in { val feeProp = settings.chainSettings.monetary.feeProposition @@ -376,7 +406,7 @@ class ErgoMemPoolSpec extends AnyFlatSpec pool.stats.snapTakenTxns shouldBe MemPoolStatistics(System.currentTimeMillis(),0,System.currentTimeMillis()).snapTakenTxns allTxs.foreach { tx => - pool = pool.remove(tx.transaction) + pool = pool.removeTxAndDoubleSpends(tx.transaction) } pool.size shouldBe 0 pool.stats.takenTxns shouldBe (family_depth + 1) * txs.size diff --git a/src/test/scala/scorex/testkit/properties/mempool/MempoolTransactionsTest.scala b/src/test/scala/scorex/testkit/properties/mempool/MempoolTransactionsTest.scala index 891c854c7e..c8ccb676bd 100644 --- a/src/test/scala/scorex/testkit/properties/mempool/MempoolTransactionsTest.scala +++ b/src/test/scala/scorex/testkit/properties/mempool/MempoolTransactionsTest.scala @@ -84,7 +84,7 @@ trait MempoolTransactionsTest property("Size of mempool should decrease when removing a present transaction") { forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => val m: ErgoMemPool = mp.put(unconfirmedTxs) - val m2: ErgoMemPool = m.remove(unconfirmedTxs.headOption.get.transaction) + val m2: ErgoMemPool = m.removeTxAndDoubleSpends(unconfirmedTxs.headOption.get.transaction) m2.size shouldBe unconfirmedTxs.size - 1 } } @@ -92,7 +92,7 @@ trait MempoolTransactionsTest property("Size of mempool should not decrease when removing a non-present transaction") { forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) => val m: ErgoMemPool = mp.put(unconfirmedTxs) - val m2: ErgoMemPool = m.remove(unconfirmedTx.transaction) + val m2: ErgoMemPool = m.removeTxAndDoubleSpends(unconfirmedTx.transaction) m2.size shouldBe unconfirmedTxs.size } } From 1d034609897dccb6f9b0f5254ca7c09cd3bc80e4 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 2 May 2024 21:12:53 +0300 Subject: [PATCH 20/36] lowering down default mempoolcleanup duration value --- .../org/ergoplatform/modifiers/history/header/Header.scala | 6 ++++-- src/main/resources/application.conf | 2 +- src/main/scala/org/ergoplatform/local/CleanupWorker.scala | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala index 092dcd219f..7f155c206f 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala @@ -53,8 +53,10 @@ case class Header(override val version: Header.Version, override val extensionRoot: Digest32, powSolution: AutolykosSolution, override val votes: Array[Byte], //3 bytes - override val sizeOpt: Option[Int] = None) extends HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, votes) with PreHeader with BlockSection { + override val sizeOpt: Option[Int] = None) extends + HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, votes) + with PreHeader with BlockSection { override def serializedId: Array[Header.Version] = Algos.hash(bytes) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 37c2406a53..d9160f10a0 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -80,7 +80,7 @@ ergo { # Interval for mempool transaction re-check. We check transaction when it is entering the mempool, and then # re-check it every interval value - mempoolCleanupDuration = 20m + mempoolCleanupDuration = 30s # Mempool transaction sorting scheme ("random", "bySize", or "byExecutionCost") mempoolSorting = "random" diff --git a/src/main/scala/org/ergoplatform/local/CleanupWorker.scala b/src/main/scala/org/ergoplatform/local/CleanupWorker.scala index 0db0c9fce8..ecc9c16e00 100644 --- a/src/main/scala/org/ergoplatform/local/CleanupWorker.scala +++ b/src/main/scala/org/ergoplatform/local/CleanupWorker.scala @@ -66,8 +66,8 @@ class CleanupWorker(nodeViewHolderRef: ActorRef, val now = System.currentTimeMillis() - val allPoolTxs = mempool.getAllPrioritized // Check transactions sorted by priority. Parent transaction comes before its children. + val allPoolTxs = mempool.getAllPrioritized val txsToValidate = allPoolTxs.filter { utx => (now - utx.lastCheckedTime) > TimeLimit }.toList From 0bc471a10997531dd3b9adbc7c6777a0fd047bd4 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 15 May 2024 11:25:35 +0300 Subject: [PATCH 21/36] alt config --- src/main/resources/application.conf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 37c2406a53..a5f6cf8a30 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -617,14 +617,14 @@ indexer-dispatcher { # Dispatcher is the name of the event-based dispatcher type = Dispatcher # What kind of ExecutionService to use - executor = "fork-join-executor" - # Configuration for the fork join pool - fork-join-executor { - # Min number of threads to cap factor-based parallelism number to - parallelism-min = 1 - # Parallelism (threads) ... ceil(available processors * factor) - parallelism-factor = 1.0 - # Max number of threads to cap factor-based parallelism number to - parallelism-max = 4 + executor = "thread-pool-executor" + # Configuration for the thread pool + thread-pool-executor { + # minimum number of threads to cap factor-based core number to + core-pool-size-min = 1 + # No of core threads ... ceil(available processors * factor) + core-pool-size-factor = 1.0 + # maximum number of threads to cap factor-based number to + core-pool-size-max = 3 } } \ No newline at end of file From 9f2d3f3dec1d98b4decea50412006bcf2e5c2b24 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 15 May 2024 11:27:18 +0300 Subject: [PATCH 22/36] Update src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala Co-authored-by: Alexander Slesarenko --- .../modifiers/mempool/ErgoNodeTransactionSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala index b8c7b73d19..8982483bb0 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala @@ -486,7 +486,7 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { /** * In this test we check how current version of the node (block protocol v3, at the moment of writing this test) will - * execute a script which contains a method added in next version of the protocol (namely, BIgInt.nbits), which + * execute a script which contains a method added in next version of the protocol (namely, BigInt.nbits), which * is unknown to the node. * * As shown in the test, rule #1110 (CheckAndGetMethod) should be replaced for new methods to be passed by the node From 9d019bad95c7395ec3940eb0187c6e92ab78dd8b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 15 May 2024 11:32:20 +0300 Subject: [PATCH 23/36] extra check for unparsed tree --- .../modifiers/mempool/ErgoNodeTransactionSpec.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala index b8c7b73d19..083626164b 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala @@ -511,6 +511,8 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { // also works val ergoTree = DefaultSerializer.deserializeErgoTree(Base16.decode("1b130206022edf0580fcf622d193db060873007301").get) + ergoTree.root.isLeft shouldBe true // unparsed + val b = new ErgoBox(1000000000L, ergoTree, Colls.emptyColl, Map.empty, ModifierId @@ "c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f7742", 0, 0) From a808c5036e57a80334348bbcea9b2e4c62cb583d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 15 May 2024 13:07:43 +0300 Subject: [PATCH 24/36] fixing imports --- .../modifiers/mempool/ErgoNodeTransactionSpec.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala index 19ecb07003..4e7969b4cc 100644 --- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoNodeTransactionSpec.scala @@ -12,7 +12,6 @@ import org.ergoplatform.nodeView.ErgoContext import org.ergoplatform.sdk.wallet.protocol.context.TransactionContext import org.ergoplatform.settings.Parameters.MaxBlockCostIncrease import org.ergoplatform.settings.ValidationRules.{bsBlockTransactionsCost, txAssetsInOneBox} -import org.ergoplatform.validation.ReplacedRule import org.ergoplatform.validation.ValidationRules.CheckAndGetMethod import org.ergoplatform.wallet.boxes.ErgoBoxAssetExtractor import org.ergoplatform.wallet.interpreter.TransactionHintsBag @@ -20,10 +19,14 @@ import org.ergoplatform.wallet.protocol.context.InputContext import org.scalacheck.Gen import sigma.util.BenchmarkUtil import scorex.crypto.hash.Blake2b256 +import scorex.util.encode.Base16 +import sigma.Colls import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.{AND, ErgoTree, TrueLeaf} +import sigma.interpreter.{ContextExtension, ProverResult} +import sigma.serialization.ErgoTreeSerializer.DefaultSerializer +import sigma.validation.ReplacedRule import sigmastate.helpers.TestingHelpers._ -import sigmastate.interpreter.{ContextExtension, ProverResult} import scala.util.{Random, Try} @@ -491,7 +494,6 @@ class ErgoNodeTransactionSpec extends ErgoCorePropertyTest { * not recognizing it. */ property("Soft-forked execution of Ergoscript containing unknown methods") { - import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer val activatedVersion = 3.toByte val params = new Parameters(0, LaunchParameters.parametersTable.updated(123, activatedVersion + 1), ErgoValidationSettingsUpdate.empty) From f5f514421e911ab496326a611cc2b268a083da5a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 22 May 2024 00:35:06 +0300 Subject: [PATCH 25/36] improved comments --- .../org/ergoplatform/modifiers/history/header/Header.scala | 6 ++---- src/main/resources/application.conf | 2 +- .../org/ergoplatform/nodeView/mempool/ErgoMemPool.scala | 7 +++++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala index e486e35fa5..c3bb9c24d8 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala @@ -54,10 +54,8 @@ case class Header(override val version: Header.Version, override val extensionRoot: Digest32, powSolution: AutolykosSolution, override val votes: Array[Byte], //3 bytes - override val sizeOpt: Option[Int] = None) extends - HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, votes) - with PreHeader with BlockSection { + override val sizeOpt: Option[Int] = None) extends HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, votes) with PreHeader with BlockSection { override def serializedId: Array[Header.Version] = Algos.hash(bytes) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index d9160f10a0..cbc5dd4382 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -79,7 +79,7 @@ ergo { mempoolCapacity = 1000 # Interval for mempool transaction re-check. We check transaction when it is entering the mempool, and then - # re-check it every interval value + # re-check it every interval value (but only on new block arrival) mempoolCleanupDuration = 30s # Mempool transaction sorting scheme ("random", "bySize", or "byExecutionCost") diff --git a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala index 76f2d543d1..58f008bfec 100644 --- a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala +++ b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala @@ -106,7 +106,7 @@ class ErgoMemPool private[mempool](private[mempool] val pool: OrderedTxPool, } /** - * Remove transaction from the pool + * Remove transaction from the pool along with its double-spends */ def removeTxAndDoubleSpends(tx: ErgoTransaction): ErgoMemPool = { def removeTx(mp: ErgoMemPool, tx: ErgoTransaction): ErgoMemPool = { @@ -126,9 +126,12 @@ class ErgoMemPool private[mempool](private[mempool] val pool: OrderedTxPool, } } + /** + * Remove provided transactions and their doublespends from the pool + */ def removeWithDoubleSpends(txs: TraversableOnce[ErgoTransaction]): ErgoMemPool = { txs.foldLeft(this) { case (memPool, tx) => - if (memPool.contains(tx.id)) { + if (memPool.contains(tx.id)) { // tx could be removed earlier in this loop as double-spend of another tx memPool.removeTxAndDoubleSpends(tx) } else { memPool From 27bc2d3e87b9cdee2eed48512234581ea867cd71 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 30 May 2024 01:08:54 +0300 Subject: [PATCH 26/36] scaladoc fixes --- .../mining/CandidateGenerator.scala | 12 ++++----- .../org/ergoplatform/mining/ErgoMiner.scala | 16 ++++++------ .../nodeView/history/ErgoHistoryReader.scala | 6 ++--- .../nodeView/history/extra/IndexedToken.scala | 2 +- .../nodeView/history/extra/Segment.scala | 4 +-- .../nodeView/state/DigestState.scala | 2 +- .../nodeView/state/UtxoState.scala | 26 +++++++++---------- .../nodeView/wallet/ErgoWalletActor.scala | 8 +++--- 8 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala index a42b50e6db..06d22db34b 100644 --- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala +++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala @@ -74,7 +74,7 @@ class CandidateGenerator( override def receive: Receive = { - /** first we need to get Readers to have some initial state to work with */ + // first we need to get Readers to have some initial state to work with case Readers(h, s: UtxoStateReader, m, _) => val lastHeaders = h.lastHeaders(500).headers val avgMiningTime = getBlockMiningTimeAvg(lastHeaders.map(_.timestamp)) @@ -118,10 +118,10 @@ class CandidateGenerator( case _: NodeViewChange => // Just ignore all other NodeView Changes - /** - * When new block is applied, either one mined by us or received from peers isn't equal to our candidate's parent, - * we need to generate new candidate and possibly also discard existing solution if it is also behind - */ + /* + * When new block is applied, either one mined by us or received from peers isn't equal to our candidate's parent, + * we need to generate new candidate and possibly also discard existing solution if it is also behind + */ case FullBlockApplied(header) => log.info( s"Preparing new candidate on getting new block at ${header.height}" @@ -884,7 +884,7 @@ object CandidateGenerator extends ScorexLogging { } /** - * Derives header without pow from [[CandidateBlock]]. + * Derives header without pow from a block candidate provided */ def deriveUnprovenHeader(candidate: CandidateBlock): HeaderWithoutPow = { val (parentId, height) = derivedHeaderFields(candidate.parentOpt) diff --git a/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala b/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala index 82b8630abd..9eec7a24c2 100644 --- a/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala +++ b/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala @@ -68,7 +68,7 @@ class ErgoMiner( override def receive: Receive = { - /** at first keep trying to obtain secret and public key as we cannot mine without it */ + // at first keep trying to obtain secret and public key as we cannot mine without it case walletQuery: WalletQuery => viewHolderRef ! GetDataFromCurrentView[DigestState, Unit] { v => walletQuery match { @@ -143,13 +143,13 @@ class ErgoMiner( case ReadMinerPk => // used in /mining/rewardAddress API method sender() ! StatusReply.success(minerState.publicKey) - /** - * Non obvious but case when mining is enabled, but miner isn't started yet. Initialization case. - * We've received block that been generated by somebody else or genesis while we doesn't start. - * And this block was generated after our miner had been started. That means that we are ready - * to start mining. - * This block could be either genesis or generated by another node. - */ + /* + * Non obvious but case when mining is enabled, but miner isn't started yet. Initialization case. + * We've received block that been generated by somebody else or genesis while we doesn't start. + * And this block was generated after our miner had been started. That means that we are ready + * to start mining. + * This block could be either genesis or generated by another node. + */ case FullBlockApplied(header) if shouldStartMine(header) => log.info("Starting mining triggered by incoming block") diff --git a/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryReader.scala b/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryReader.scala index 3fde451134..9f7a45f0fe 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryReader.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryReader.scala @@ -361,9 +361,9 @@ trait ErgoHistoryReader * @return */ def syncInfoV1: ErgoSyncInfoV1 = { - /** - * Return last count headers from best headers chain if exist or chain up to genesis otherwise - */ + /* + * Return last count headers from best headers chain if exist or chain up to genesis otherwise + */ def lastHeaderIds(count: Int): IndexedSeq[ModifierId] = { val currentHeight = headersHeight val from = Math.max(currentHeight - count + 1, 1) diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala index e29b0fc04d..a6449f4027 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala @@ -167,7 +167,7 @@ object IndexedToken { * so they are checked with Try-catches. * * @param iEb - box to use - * @param tokenIndex - token index to check in [[ErgoBox.additionalTokens]] + * @param tokenIndex - token index to check in box' `additionalTokens` * @return token index */ def fromBox(iEb: IndexedErgoBox, tokenIndex: Int): IndexedToken = { diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/Segment.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/Segment.scala index c45a5c9595..572f2043c1 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/Segment.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/Segment.scala @@ -244,7 +244,7 @@ abstract class Segment[T <: Segment[_] : ClassTag](val parentId: ModifierId, * @param mempool - mempool to use, if unconfirmed is true * @param offset - items to skip from the start * @param limit - items to retrieve - * @param sortDir - whether to start retreival from newest box ([[DESC]]) or oldest box ([[ASC]]) + * @param sortDir - whether to start retrieval from newest box (DESC) or oldest box (ASC) * @param unconfirmed - whether to include unconfirmed boxes * @return array of unspent boxes */ @@ -288,7 +288,7 @@ abstract class Segment[T <: Segment[_] : ClassTag](val parentId: ModifierId, } /** - * Logic for [[Segment.rollback]] + * Logic for `Segment.rollback` * * @param txTarget - remove transaction numbers above this number * @param boxTarget - remove box numbers above this number diff --git a/src/main/scala/org/ergoplatform/nodeView/state/DigestState.scala b/src/main/scala/org/ergoplatform/nodeView/state/DigestState.scala index 3c5a3a4721..94a51540b7 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/DigestState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/DigestState.scala @@ -154,7 +154,7 @@ class DigestState protected(override val version: VersionTag, object DigestState extends ScorexLogging with ScorexEncoding { /** - * Creates [[DigestState]] from existing [[ErgoStateContext]] corresponding to some `version` and `rootHash`. + * Creates [[DigestState]] with provided `ErgoStateContext` instance corresponding to some version` and `rootHash`. */ def recover(version: VersionTag, rootHash: ADDigest, diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala index 01b98a59ef..a16f29265b 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala @@ -159,19 +159,19 @@ class UtxoState(override val persistentProver: PersistentBatchAVLProver[Digest32 log.error("Calculated proofHash is not equal to the declared one, doing another attempt") - /** - * Proof generated was different from one announced. - * - * In most cases, announced proof is okay, and as proof is already checked, problem in some - * extra bytes added to the proof. - * - * Could be related to https://github.com/ergoplatform/ergo/issues/1614 - * - * So the problem could appear on mining nodes only, and caused by - * proofsForTransactions() wasting the tree unexpectedly. - * - * We are trying to generate proof again now. - */ + /* + * Proof generated was different from one announced. + * + * In most cases, announced proof is okay, and as proof is already checked, problem in some + * extra bytes added to the proof. + * + * Could be related to https://github.com/ergoplatform/ergo/issues/1614 + * + * So the problem could appear on mining nodes only, and caused by + * proofsForTransactions() wasting the tree unexpectedly. + * + * We are trying to generate proof again now. + */ persistentProver.rollback(inRoot) .ensuring(java.util.Arrays.equals(persistentProver.digest, inRoot)) diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala index c65599f212..b64b43522f 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala @@ -116,7 +116,7 @@ class ErgoWalletActor(settings: ErgoSettings, case _: RestoreWallet | _: InitWallet => sender() ! Failure(new Exception("Wallet is already initialized or testMnemonic is set. Clear current secret to re-init it.")) - /** READERS */ + /* READERS */ case ReadBalances(chainStatus) => val walletDigest = if (chainStatus.onChain) { state.registry.fetchDigest() @@ -194,7 +194,7 @@ class ErgoWalletActor(settings: ErgoSettings, case ReadScans => sender() ! ReadScansResponse(state.walletVars.externalScans) - /** STATE CHANGE */ + /* STATE CHANGE */ case ChangedMempool(mr: ErgoMemPoolReader@unchecked) => val newState = ergoWalletService.updateUtxoState(state.copy(mempoolReaderOpt = Some(mr))) context.become(loadedWallet(newState)) @@ -219,7 +219,7 @@ class ErgoWalletActor(settings: ErgoSettings, context.become(loadedWallet(state.copy(error = Some(errorMsg)))) } - /** SCAN COMMANDS */ + /* SCAN COMMANDS */ //scan mempool transaction case ScanOffChain(tx) => val dustLimit = settings.walletSettings.dustLimit @@ -300,7 +300,7 @@ class ErgoWalletActor(settings: ErgoSettings, log.warn("Avoiding rollback as wallet is not initialized yet") } - /** WALLET COMMANDS */ + /* WALLET COMMANDS */ case CheckSeed(mnemonic, passOpt) => state.secretStorageOpt match { case Some(secretStorage) => From 0368715b4d4ecdc83d47051d3f16895677f71215 Mon Sep 17 00:00:00 2001 From: mgpai <64056966+mgpai22@users.noreply.github.com> Date: Thu, 30 May 2024 13:31:41 -0400 Subject: [PATCH 27/36] add token info post api --- .../ergoplatform/http/api/BlockchainApiRoute.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala index 0be225d035..0c393eee41 100644 --- a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala @@ -85,6 +85,7 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting getBoxesByErgoTreeR ~ getBoxesByErgoTreeUnspentR ~ getTokenInfoByIdR ~ + getTokenInfoByIdsR ~ getAddressBalanceTotalR ~ getAddressBalanceTotalGetRoute } @@ -326,6 +327,12 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting } } + private def getTokenInfoByIds(ids: Seq[ModifierId]): Future[Seq[IndexedToken]] = { + getHistory.map { history => + ids.flatMap(id => history.typedExtraIndexById[IndexedToken](uniqueId(id))) + } + } + private def getTokenInfoById(id: ModifierId): Future[Option[IndexedToken]] = { getHistory.map { history => history.typedExtraIndexById[IndexedToken](uniqueId(id)) @@ -336,6 +343,10 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting ApiResponse(getTokenInfoById(id)) } + private def getTokenInfoByIdsR: Route = (post & pathPrefix("tokens") & entity(as[Seq[ModifierId]])) { ids => + ApiResponse(getTokenInfoByIds(ids)) + } + private def getBoxesByTokenId(id: ModifierId, offset: Int, limit: Int): Future[(Seq[IndexedErgoBox],Long)] = getHistory.map { history => history.typedExtraIndexById[IndexedToken](uniqueId(id)) match { From e4a1d5e5f864d5b35307f2fc5109d46f18669881 Mon Sep 17 00:00:00 2001 From: mgpai <64056966+mgpai22@users.noreply.github.com> Date: Thu, 30 May 2024 13:32:12 -0400 Subject: [PATCH 28/36] update open api for token info post --- src/main/resources/api/openapi.yaml | 31 ++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/resources/api/openapi.yaml b/src/main/resources/api/openapi.yaml index a49f06f81c..271a44b6e5 100644 --- a/src/main/resources/api/openapi.yaml +++ b/src/main/resources/api/openapi.yaml @@ -6636,7 +6636,36 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiError' - + /blockchain/tokens: + post: + summary: Retrieve minting information about a list of tokens + operationId: getTokensByIds + tags: + - blockchain + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: string + description: Token ID + responses: + '200': + description: Array of tokens with the provided IDs + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/IndexedToken' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' /blockchain/balance: post: summary: Retrieve confirmed and unconfirmed balance of an address From f7b0e86db45e3f0ccec9c52d4b807076e5a1a7fb Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 21 Jun 2024 15:03:03 +0300 Subject: [PATCH 29/36] node.utxoBootstrap fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9efcc702f2..b49d4aecea 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ By default, the node processes all blocks from the genesis block. However, there ergo { ... - node.utxoBootstrap = true + node.utxo.utxoBootstrap = true ... } ``` From 88dcf1d4c58f5ab4f96e9fef6f3fc6fd12df5782 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 12 Aug 2024 23:33:09 +0300 Subject: [PATCH 30/36] fixed /wallet/getPrivateKey description --- src/main/resources/api/openapi.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/resources/api/openapi.yaml b/src/main/resources/api/openapi.yaml index f3f3545e72..91defefecf 100644 --- a/src/main/resources/api/openapi.yaml +++ b/src/main/resources/api/openapi.yaml @@ -1302,6 +1302,15 @@ components: type: string description: hex-encoded serialized box bytes + PrivateKeyRequest: + description: Request for getting a secret corresponding to wallet address + type: object + required: + - address + properties: + address: + $ref: '#/components/schemas/ErgoAddress' + PaymentRequest: description: Request for generation of payment transaction to a given address type: object @@ -4881,7 +4890,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/ErgoAddress" + $ref: "#/components/schemas/PrivateKeyRequest" responses: '200': description: Successfully retrieved secret key From a307a2c9a33db6c7ce73d96c5ec96d50c7a6a6bf Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 5 Sep 2024 01:36:17 +0300 Subject: [PATCH 31/36] only one non-default threadpool left --- src/main/resources/application.conf | 37 ------------------- .../org/ergoplatform/GlobalConstants.scala | 15 -------- .../nodeView/ErgoReadersHolder.scala | 3 +- .../nodeView/history/extra/ExtraIndexer.scala | 4 +- .../nodeView/wallet/ErgoWalletActor.scala | 1 - 5 files changed, 3 insertions(+), 57 deletions(-) delete mode 100644 src/main/scala/org/ergoplatform/GlobalConstants.scala diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index d69db467c0..7b1e91eb31 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -590,41 +590,4 @@ critical-dispatcher { fixed-pool-size = 2 } throughput = 1 -} - -# dispatcher for some API-related actors -api-dispatcher { - # Dispatcher is the name of the event-based dispatcher - type = Dispatcher - # What kind of ExecutionService to use - executor = "fork-join-executor" - # Configuration for the fork join pool - fork-join-executor { - # Min number of threads to cap factor-based parallelism number to - parallelism-min = 1 - # Parallelism (threads) ... ceil(available processors * factor) - parallelism-factor = 2.0 - # Max number of threads to cap factor-based parallelism number to - parallelism-max = 2 - } - # Throughput defines the maximum number of messages to be - # processed per actor before the thread jumps to the next actor. - # Set to 1 for as fair as possible. - throughput = 4 -} - -indexer-dispatcher { - # Dispatcher is the name of the event-based dispatcher - type = Dispatcher - # What kind of ExecutionService to use - executor = "thread-pool-executor" - # Configuration for the thread pool - thread-pool-executor { - # minimum number of threads to cap factor-based core number to - core-pool-size-min = 1 - # No of core threads ... ceil(available processors * factor) - core-pool-size-factor = 1.0 - # maximum number of threads to cap factor-based number to - core-pool-size-max = 3 - } } \ No newline at end of file diff --git a/src/main/scala/org/ergoplatform/GlobalConstants.scala b/src/main/scala/org/ergoplatform/GlobalConstants.scala deleted file mode 100644 index 5d396394ba..0000000000 --- a/src/main/scala/org/ergoplatform/GlobalConstants.scala +++ /dev/null @@ -1,15 +0,0 @@ -package org.ergoplatform - -/** - * A singleton which holds constants needed around the whole Ergo Platform. - */ -object GlobalConstants { - - /** - * Name of dispatcher for actors processing API requests - * (to avoid clashing between blockchain processing and API actors) - */ - val ApiDispatcher = "api-dispatcher" - - val IndexerDispatcher = "indexer-dispatcher" -} diff --git a/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala b/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala index a7df32ee3f..8ff1f1f710 100644 --- a/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala +++ b/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala @@ -1,7 +1,6 @@ package org.ergoplatform.nodeView import akka.actor.{Actor, ActorRef, ActorRefFactory, Props} -import org.ergoplatform.GlobalConstants import org.ergoplatform.nodeView.ErgoReadersHolder._ import org.ergoplatform.nodeView.history.ErgoHistoryReader import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader @@ -69,7 +68,7 @@ object ErgoReadersHolderRef { def apply(viewHolderRef: ActorRef) (implicit context: ActorRefFactory): ActorRef = { - val props = Props(new ErgoReadersHolder(viewHolderRef)).withDispatcher(GlobalConstants.ApiDispatcher) + val props = Props(new ErgoReadersHolder(viewHolderRef)) context.actorOf(props) } diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala index 4cd9fe5986..c91e6f481e 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala @@ -2,7 +2,7 @@ package org.ergoplatform.nodeView.history.extra import akka.actor.{Actor, ActorRef, ActorSystem, Props, Stash} import org.ergoplatform.ErgoBox.TokenId -import org.ergoplatform.{ErgoAddress, ErgoAddressEncoder, GlobalConstants, Pay2SAddress} +import org.ergoplatform.{ErgoAddress, ErgoAddressEncoder, Pay2SAddress} import org.ergoplatform.modifiers.history.BlockTransactions import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.ErgoTransaction @@ -584,6 +584,6 @@ object ExtraIndexer { def apply(chainSettings: ChainSettings, cacheSettings: CacheSettings)(implicit system: ActorSystem): ActorRef = { val props = Props.create(classOf[ExtraIndexer], cacheSettings, chainSettings.addressEncoder) - system.actorOf(props.withDispatcher(GlobalConstants.IndexerDispatcher)) + system.actorOf(props) } } diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala index b64b43522f..41e48f9fb8 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala @@ -509,7 +509,6 @@ object ErgoWalletActor extends ScorexLogging { boxSelector: BoxSelector, historyReader: ErgoHistoryReader)(implicit actorSystem: ActorSystem): ActorRef = { val props = Props(classOf[ErgoWalletActor], settings, parameters, service, boxSelector, historyReader) - .withDispatcher(GlobalConstants.ApiDispatcher) val walletActorRef = actorSystem.actorOf(props) CoordinatedShutdown(actorSystem).addActorTerminationTask( CoordinatedShutdown.PhaseBeforeServiceUnbind, From 283c57031bb71fcd03ac9471ac42f6cd049be77b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 19 Sep 2024 12:03:40 +0300 Subject: [PATCH 32/36] filling up blockCache in 1 thread only --- .../nodeView/history/extra/ExtraIndexer.scala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala index c91e6f481e..1a81fb3f08 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala @@ -90,13 +90,13 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { if (readingUpTo - height < 300 && chainHeight - height > 1000) { readingUpTo = math.min(height + 1001, chainHeight) val blockNums = height + 1 to readingUpTo by 50 - blockNums.zip(blockNums.tail).map { range => // ranges of 50 blocks for each thread to read - Future { + Future { + blockNums.zip(blockNums.tail).map { range => // ranges of 50 blocks for each thread to read (range._1 until range._2).foreach { blockNum => history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) } - }(context.dispatcher) - } + } + }(context.dispatcher) } txs } @@ -237,7 +237,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { }.orElse(getBlockTransactionsAt(state.indexedHeight)) val height = headerOpt.map(_.height).getOrElse(state.indexedHeight) - if(btOpt.isEmpty) { + if (btOpt.isEmpty) { log.warn(s"Could not read block $height / $chainHeight from database, waiting for new block until retrying") return state.decrementIndexedHeight.copy(caughtUp = true) } @@ -411,7 +411,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { val newState: IndexerState = index(state.incrementIndexedHeight, Some(header)) saveProgress(newState) context.become(loaded(newState)) - } else if(header.height > state.indexedHeight + 1) { // applied block is ahead of indexer + } else if (header.height > state.indexedHeight + 1) { // applied block is ahead of indexer context.become(loaded(state.copy(caughtUp = false))) self ! Index() } else // applied block has already been indexed, skipping duplicate @@ -425,8 +425,8 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { history.heightOf(branchPoint) match { case Some(branchHeight) => if (branchHeight < state.indexedHeight) { - context.become (loaded (state.copy (rollbackTo = branchHeight) ) ) - self ! RemoveAfter (branchHeight) + context.become(loaded(state.copy(rollbackTo = branchHeight))) + self ! RemoveAfter(branchHeight) } case None => log.error(s"No rollback height found for $branchPoint") From 3705aba4bbfa61c8301ef550ec401e38c3d6bebf Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 24 Sep 2024 15:01:26 +0300 Subject: [PATCH 33/36] improving comments and getBlockTransactionsAt --- .../modifiers/history/header/HeaderSerializer.scala | 3 ++- .../nodeView/history/extra/ExtraIndexer.scala | 8 +++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala index d6d72f1aa4..c7688bac61 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala @@ -30,7 +30,8 @@ object HeaderSerializer extends ErgoSerializer[Header] { w.putBytes(h.votes) // For block version >= 2, this new byte encodes length of possible new fields. - // Set to 0 for now, so no new fields. + // starting from 5.0.23, new fields also included. + // They should be added in >= 5 bock version, see serializer if (h.version > Header.InitialVersion) { w.putUByte(h.unparsedBytes.length) w.putBytes(h.unparsedBytes) diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala index 1a81fb3f08..4fd1541239 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala @@ -89,12 +89,10 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { if (height % 1000 == 0) blockCache.keySet.filter(_ < height).map(blockCache.remove) if (readingUpTo - height < 300 && chainHeight - height > 1000) { readingUpTo = math.min(height + 1001, chainHeight) - val blockNums = height + 1 to readingUpTo by 50 + val blockNums = height + 1 to readingUpTo Future { - blockNums.zip(blockNums.tail).map { range => // ranges of 50 blocks for each thread to read - (range._1 until range._2).foreach { blockNum => - history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) - } + blockNums.foreach { blockNum => + history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) } }(context.dispatcher) } From 756a8bbed650c0964092a77412c0cece80caf900 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 24 Sep 2024 15:11:58 +0300 Subject: [PATCH 34/36] single or multi threaded block cache filling --- .../nodeView/history/extra/ExtraIndexer.scala | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala index 4fd1541239..1a3cd221eb 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala @@ -89,12 +89,24 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { if (height % 1000 == 0) blockCache.keySet.filter(_ < height).map(blockCache.remove) if (readingUpTo - height < 300 && chainHeight - height > 1000) { readingUpTo = math.min(height + 1001, chainHeight) - val blockNums = height + 1 to readingUpTo - Future { - blockNums.foreach { blockNum => - history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) + + if(height < history.fullBlockHeight - 1000) { + val blockNums = height + 1 to readingUpTo by 250 + blockNums.zip(blockNums.tail).map { range => // ranges of 250 blocks for each thread to read + Future { + (range._1 until range._2).foreach { blockNum => + history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) + } + }(context.dispatcher) } - }(context.dispatcher) + } else { + val blockNums = height + 1 to readingUpTo + Future { + blockNums.foreach { blockNum => + history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) + } + }(context.dispatcher) + } } txs } From 003bb84731f6ea797690d1af4f322a5067f6181b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 30 Sep 2024 23:57:09 +0300 Subject: [PATCH 35/36] getting dispatchers back --- src/main/resources/application.conf | 37 +++++++++++++++++++ .../org/ergoplatform/GlobalConstants.scala | 16 ++++++++ .../nodeView/ErgoReadersHolder.scala | 3 +- .../nodeView/history/extra/ExtraIndexer.scala | 14 ++++--- .../nodeView/wallet/ErgoWalletActor.scala | 1 + 5 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 src/main/scala/org/ergoplatform/GlobalConstants.scala diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 7b1e91eb31..cbc5dd4382 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -590,4 +590,41 @@ critical-dispatcher { fixed-pool-size = 2 } throughput = 1 +} + +# dispatcher for some API-related actors +api-dispatcher { + # Dispatcher is the name of the event-based dispatcher + type = Dispatcher + # What kind of ExecutionService to use + executor = "fork-join-executor" + # Configuration for the fork join pool + fork-join-executor { + # Min number of threads to cap factor-based parallelism number to + parallelism-min = 1 + # Parallelism (threads) ... ceil(available processors * factor) + parallelism-factor = 2.0 + # Max number of threads to cap factor-based parallelism number to + parallelism-max = 2 + } + # Throughput defines the maximum number of messages to be + # processed per actor before the thread jumps to the next actor. + # Set to 1 for as fair as possible. + throughput = 4 +} + +indexer-dispatcher { + # Dispatcher is the name of the event-based dispatcher + type = Dispatcher + # What kind of ExecutionService to use + executor = "fork-join-executor" + # Configuration for the fork join pool + fork-join-executor { + # Min number of threads to cap factor-based parallelism number to + parallelism-min = 1 + # Parallelism (threads) ... ceil(available processors * factor) + parallelism-factor = 1.0 + # Max number of threads to cap factor-based parallelism number to + parallelism-max = 4 + } } \ No newline at end of file diff --git a/src/main/scala/org/ergoplatform/GlobalConstants.scala b/src/main/scala/org/ergoplatform/GlobalConstants.scala new file mode 100644 index 0000000000..2536689a4f --- /dev/null +++ b/src/main/scala/org/ergoplatform/GlobalConstants.scala @@ -0,0 +1,16 @@ +package org.ergoplatform + +/** + * A singleton which holds constants needed around the whole Ergo Platform. + */ +object GlobalConstants { + + /** + * Name of dispatcher for actors processing API requests + * (to avoid clashing between blockchain processing and API actors) + */ + val ApiDispatcher = "api-dispatcher" + + val IndexerDispatcher = "indexer-dispatcher" + +} diff --git a/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala b/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala index 8ff1f1f710..a7df32ee3f 100644 --- a/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala +++ b/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala @@ -1,6 +1,7 @@ package org.ergoplatform.nodeView import akka.actor.{Actor, ActorRef, ActorRefFactory, Props} +import org.ergoplatform.GlobalConstants import org.ergoplatform.nodeView.ErgoReadersHolder._ import org.ergoplatform.nodeView.history.ErgoHistoryReader import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader @@ -68,7 +69,7 @@ object ErgoReadersHolderRef { def apply(viewHolderRef: ActorRef) (implicit context: ActorRefFactory): ActorRef = { - val props = Props(new ErgoReadersHolder(viewHolderRef)) + val props = Props(new ErgoReadersHolder(viewHolderRef)).withDispatcher(GlobalConstants.ApiDispatcher) context.actorOf(props) } diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala index 1a3cd221eb..29636c920a 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala @@ -2,7 +2,7 @@ package org.ergoplatform.nodeView.history.extra import akka.actor.{Actor, ActorRef, ActorSystem, Props, Stash} import org.ergoplatform.ErgoBox.TokenId -import org.ergoplatform.{ErgoAddress, ErgoAddressEncoder, Pay2SAddress} +import org.ergoplatform.{ErgoAddress, ErgoAddressEncoder, GlobalConstants, Pay2SAddress} import org.ergoplatform.modifiers.history.BlockTransactions import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.ErgoTransaction @@ -25,7 +25,7 @@ import spire.syntax.all.cfor import java.util.concurrent.ConcurrentHashMap import scala.collection.mutable import scala.collection.concurrent -import scala.concurrent.Future +import scala.concurrent.{ExecutionContextExecutor, Future} import scala.jdk.CollectionConverters._ /** @@ -33,6 +33,8 @@ import scala.jdk.CollectionConverters._ */ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { + private implicit val ec: ExecutionContextExecutor = context.dispatcher + /** * Max buffer size (determined by config) */ @@ -97,7 +99,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { (range._1 until range._2).foreach { blockNum => history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) } - }(context.dispatcher) + } } } else { val blockNums = height + 1 to readingUpTo @@ -105,7 +107,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { blockNums.foreach { blockNum => history.bestBlockTransactionsAt(blockNum).map(blockCache.put(blockNum, _)) } - }(context.dispatcher) + } } } txs @@ -248,7 +250,7 @@ trait ExtraIndexerBase extends Actor with Stash with ScorexLogging { val height = headerOpt.map(_.height).getOrElse(state.indexedHeight) if (btOpt.isEmpty) { - log.warn(s"Could not read block $height / $chainHeight from database, waiting for new block until retrying") + log.error(s"Could not read block $height / $chainHeight from database, waiting for new block until retrying") return state.decrementIndexedHeight.copy(caughtUp = true) } @@ -594,6 +596,6 @@ object ExtraIndexer { def apply(chainSettings: ChainSettings, cacheSettings: CacheSettings)(implicit system: ActorSystem): ActorRef = { val props = Props.create(classOf[ExtraIndexer], cacheSettings, chainSettings.addressEncoder) - system.actorOf(props) + system.actorOf(props.withDispatcher(GlobalConstants.IndexerDispatcher)) } } diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala index 41e48f9fb8..b64b43522f 100644 --- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala +++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala @@ -509,6 +509,7 @@ object ErgoWalletActor extends ScorexLogging { boxSelector: BoxSelector, historyReader: ErgoHistoryReader)(implicit actorSystem: ActorSystem): ActorRef = { val props = Props(classOf[ErgoWalletActor], settings, parameters, service, boxSelector, historyReader) + .withDispatcher(GlobalConstants.ApiDispatcher) val walletActorRef = actorSystem.actorOf(props) CoordinatedShutdown(actorSystem).addActorTerminationTask( CoordinatedShutdown.PhaseBeforeServiceUnbind, From 88e0aedde74c9aff805a2e20ecea7a4749e2ea3c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 10 Oct 2024 12:05:00 +0300 Subject: [PATCH 36/36] lazy segmentThreshold --- src/main/scala/org/ergoplatform/ErgoApp.scala | 17 +++++++++-------- .../http/api/BlockchainApiRoute.scala | 10 +++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/scala/org/ergoplatform/ErgoApp.scala b/src/main/scala/org/ergoplatform/ErgoApp.scala index 323bd5f227..cf8ad93170 100644 --- a/src/main/scala/org/ergoplatform/ErgoApp.scala +++ b/src/main/scala/org/ergoplatform/ErgoApp.scala @@ -106,14 +106,6 @@ class ErgoApp(args: Args) extends ScorexLogging { None } - // Create an instance of ExtraIndexer actor (will start if "extraIndex = true" in config) - private val indexerOpt: Option[ActorRef] = - if (ergoSettings.nodeSettings.extraIndex) { - Some(ExtraIndexer(ergoSettings.chainSettings, ergoSettings.cacheSettings)) - } else { - None - } - private val syncTracker = ErgoSyncTracker(scorexSettings.network) private val deliveryTracker: DeliveryTracker = DeliveryTracker.empty(ergoSettings) @@ -144,6 +136,7 @@ class ErgoApp(args: Args) extends ScorexLogging { ManifestSpec.messageCode -> ergoNodeViewSynchronizerRef, GetUtxoSnapshotChunkSpec.messageCode-> ergoNodeViewSynchronizerRef, UtxoSnapshotChunkSpec.messageCode -> ergoNodeViewSynchronizerRef, + // nipopows exchange related messages GetNipopowProofSpec.messageCode -> ergoNodeViewSynchronizerRef, NipopowProofSpec.messageCode -> ergoNodeViewSynchronizerRef ) @@ -179,6 +172,14 @@ class ErgoApp(args: Args) extends ScorexLogging { ergoSettings ) + // Create an instance of ExtraIndexer actor (will start if "extraIndex = true" in config) + private val indexerOpt: Option[ActorRef] = + if (ergoSettings.nodeSettings.extraIndex) { + Some(ExtraIndexer(ergoSettings.chainSettings, ergoSettings.cacheSettings)) + } else { + None + } + private val apiRoutes: Seq[ApiRoute] = Seq( EmissionApiRoute(ergoSettings), ErgoUtilsApiRoute(ergoSettings), diff --git a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala index 355efd2912..7e05ecdd8e 100644 --- a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala @@ -32,7 +32,7 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting val settings: RESTApiSettings = ergoSettings.scorexSettings.restApi - private implicit val segmentTreshold: Int = indexerOpt.map { indexer => + private lazy val segmentTreshold: Int = indexerOpt.map { indexer => Await.result[Int]((indexer ? GetSegmentThreshold).asInstanceOf[Future[Int]], Duration(3, SECONDS)) }.getOrElse(0) @@ -152,7 +152,7 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting private def getTxsByAddress(addr: ErgoAddress, offset: Int, limit: Int): Future[(Seq[IndexedErgoTransaction],Long)] = getHistory.map { history => getAddress(addr)(history) match { - case Some(addr) => (addr.retrieveTxs(history, offset, limit), addr.txCount) + case Some(addr) => (addr.retrieveTxs(history, offset, limit)(segmentTreshold), addr.txCount(segmentTreshold)) case None => (Seq.empty[IndexedErgoTransaction], 0L) } } @@ -220,7 +220,7 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting private def getBoxesByAddress(addr: ErgoAddress, offset: Int, limit: Int): Future[(Seq[IndexedErgoBox],Long)] = getHistory.map { history => getAddress(addr)(history) match { - case Some(addr) => (addr.retrieveBoxes(history, offset, limit).reverse, addr.boxCount) + case Some(addr) => (addr.retrieveBoxes(history, offset, limit)(segmentTreshold).reverse, addr.boxCount(segmentTreshold)) case None => (Seq.empty[IndexedErgoBox], 0L) } } @@ -312,7 +312,7 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting private def getBoxesByErgoTree(tree: ErgoTree, offset: Int, limit: Int): Future[(Seq[IndexedErgoBox],Long)] = getHistory.map { history => getAddress(tree)(history) match { - case Some(iEa) => (iEa.retrieveBoxes(history, offset, limit).reverse, iEa.boxCount) + case Some(iEa) => (iEa.retrieveBoxes(history, offset, limit)(segmentTreshold).reverse, iEa.boxCount(segmentTreshold)) case None => (Seq.empty[IndexedErgoBox], 0L) } } @@ -365,7 +365,7 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting private def getBoxesByTokenId(id: ModifierId, offset: Int, limit: Int): Future[(Seq[IndexedErgoBox],Long)] = getHistory.map { history => history.typedExtraIndexById[IndexedToken](uniqueId(id)) match { - case Some(token) => (token.retrieveBoxes(history, offset, limit), token.boxCount) + case Some(token) => (token.retrieveBoxes(history, offset, limit)(segmentTreshold), token.boxCount(segmentTreshold)) case None => (Seq.empty[IndexedErgoBox], 0L) } }