From 308627c66584f9c7acc80aad3d3fc3f922c2dba8 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Tue, 22 Mar 2022 12:51:43 +0300 Subject: [PATCH 01/13] Add adProofsSuffixLength to NodeConfigurationSettings refer #1658 --- src/main/resources/application.conf | 3 +++ src/main/resources/testnet.conf | 5 ++++- .../scala/org/ergoplatform/nodeView/state/UtxoState.scala | 6 ++++-- .../ergoplatform/settings/NodeConfigurationSettings.scala | 2 ++ src/test/resources/application.conf | 3 +++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 70e300ab31..73e2a5d0c8 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -95,6 +95,9 @@ ergo { # The node still applying transactions to UTXO set and so checks UTXO set digests for each block. # Block at checkpoint height is to be checked against expected one. checkpoint = null + + # Dump ADProofs only for the suffix given during bootstrapping + dProofsSuffixLength = 114688 // 112k } cache { diff --git a/src/main/resources/testnet.conf b/src/main/resources/testnet.conf index 68a9741269..ca9e5c9b86 100644 --- a/src/main/resources/testnet.conf +++ b/src/main/resources/testnet.conf @@ -17,7 +17,10 @@ ergo { # maximum cost of transaction for it to be propagated maxTransactionCost = 800000 - } + + # Dump ADProofs only for the suffix given during bootstrapping + dProofsSuffixLength = 114688 // 112k + } chain { # Network address prefix, currently reserved values are 0 (money chain mainnet) and 16 (money chain testnet) diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala index 8611e7f4fc..d72b1dd98a 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala @@ -167,8 +167,10 @@ class UtxoState(override val persistentProver: PersistentBatchAVLProver[Digest32 } if (fb.adProofs.isEmpty) { - val adProofs = ADProofs(fb.header.id, proofBytes) - generate(LocallyGeneratedModifier(adProofs)) + if (fb.height >= estimatedTip.getOrElse(Int.MaxValue) - stateContext.ergoSettings.nodeSettings.adProofsSuffixLength) { + val adProofs = ADProofs(fb.header.id, proofBytes) + generate(LocallyGeneratedModifier(adProofs)) + } } log.info(s"Valid modifier with header ${fb.header.encodedId} and emission box " + diff --git a/src/main/scala/org/ergoplatform/settings/NodeConfigurationSettings.scala b/src/main/scala/org/ergoplatform/settings/NodeConfigurationSettings.scala index 1b9cea0159..410f844601 100644 --- a/src/main/scala/org/ergoplatform/settings/NodeConfigurationSettings.scala +++ b/src/main/scala/org/ergoplatform/settings/NodeConfigurationSettings.scala @@ -44,6 +44,7 @@ case class NodeConfigurationSettings(stateType: StateType, rebroadcastCount: Int, minimalFeeAmount: Long, headerChainDiff: Int, + adProofsSuffixLength: Int, blacklistedTransactions: Seq[String] = Seq.empty, checkpoint: Option[CheckpointSettings] = None) { /** @@ -79,6 +80,7 @@ trait NodeConfigurationReaders extends StateTypeReaders with CheckpointingSettin cfg.as[Int](s"$path.rebroadcastCount"), cfg.as[Long](s"$path.minimalFeeAmount"), cfg.as[Int](s"$path.headerChainDiff"), + cfg.as[Int](s"$path.adProofsSuffixLength"), cfg.as[Seq[String]](s"$path.blacklistedTransactions"), cfg.as[Option[CheckpointSettings]](s"$path.checkpoint") ) diff --git a/src/test/resources/application.conf b/src/test/resources/application.conf index b874e974ec..0e81d9911d 100644 --- a/src/test/resources/application.conf +++ b/src/test/resources/application.conf @@ -56,6 +56,9 @@ ergo { # than headerChainDiff blocks on average from future # for tests, the value is 100 (as in mainnet) headerChainDiff = 100 + + # Dump ADProofs only for the suffix given during bootstrapping + dProofsSuffixLength = 114688 // 112k } cache { From 5d21a0e6d92cd5d8f5b4401bd320d9552825f899 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Tue, 22 Mar 2022 12:57:26 +0300 Subject: [PATCH 02/13] Fix intialization of adProofsSuffixLength for NodeConfigurationSettings refer #1658 --- .../settings/ErgoSettingsSpecification.scala | 9 ++++++--- .../scala/org/ergoplatform/tools/ChainGenerator.scala | 2 +- .../org/ergoplatform/utils/HistoryTestHelpers.scala | 3 ++- src/test/scala/org/ergoplatform/utils/Stubs.scala | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala b/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala index 022252174d..634fafafda 100644 --- a/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala +++ b/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala @@ -37,7 +37,8 @@ class ErgoSettingsSpecification extends ErgoPropertyTest { mempoolCleanupDuration = 10.seconds, rebroadcastCount = 3, minimalFeeAmount = 0, - headerChainDiff = 100 + headerChainDiff = 100, + adProofsSuffixLength = 112*1024 ) settings.cacheSettings shouldBe CacheSettings( HistoryCacheSettings( @@ -80,7 +81,8 @@ class ErgoSettingsSpecification extends ErgoPropertyTest { mempoolCleanupDuration = 10.seconds, rebroadcastCount = 3, minimalFeeAmount = 0, - headerChainDiff = 100 + headerChainDiff = 100, + adProofsSuffixLength = 112*1024 ) settings.cacheSettings shouldBe CacheSettings( HistoryCacheSettings( @@ -123,7 +125,8 @@ class ErgoSettingsSpecification extends ErgoPropertyTest { mempoolCleanupDuration = 10.seconds, rebroadcastCount = 3, minimalFeeAmount = 0, - headerChainDiff = 100 + headerChainDiff = 100, + adProofsSuffixLength = 112*1024 ) settings.cacheSettings shouldBe CacheSettings( HistoryCacheSettings( diff --git a/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala b/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala index 418765b82d..beb562f75c 100644 --- a/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala +++ b/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala @@ -60,7 +60,7 @@ object ChainGenerator extends App with ErgoTestHelpers { val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(StateType.Utxo, verifyTransactions = true, -1, poPoWBootstrap = false, minimalSuffix, mining = false, txCostLimit, txSizeLimit, useExternalMiner = false, internalMinersCount = 1, internalMinerPollingInterval = 1.second, miningPubKeyHex = None, offlineGeneration = false, - 200, 5.minutes, 100000, 1.minute, rebroadcastCount = 20, 1000000, 100) + 200, 5.minutes, 100000, 1.minute, rebroadcastCount = 20, 1000000, 100, adProofsSuffixLength = 112*1024) val ms = settings.chainSettings.monetary.copy( minerRewardDelay = RewardDelay ) diff --git a/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala b/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala index 6810d895a8..7ca3c97351 100644 --- a/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala +++ b/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala @@ -47,7 +47,8 @@ trait HistoryTestHelpers extends ErgoPropertyTest { val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(stateType, verifyTransactions, blocksToKeep, PoPoWBootstrap, minimalSuffix, mining = false, txCostLimit, txSizeLimit, useExternalMiner = false, internalMinersCount = 1, internalMinerPollingInterval = 1.second, miningPubKeyHex = None, - offlineGeneration = false, 200, 5.minutes, 100000, 1.minute, rebroadcastCount = 200, 1000000, 100) + offlineGeneration = false, 200, 5.minutes, 100000, 1.minute, rebroadcastCount = 200, 1000000, 100, adProofsSuffixLength = 112*1024 +) val scorexSettings: ScorexSettings = null val walletSettings: WalletSettings = null val chainSettings = initialDiffOpt match { diff --git a/src/test/scala/org/ergoplatform/utils/Stubs.scala b/src/test/scala/org/ergoplatform/utils/Stubs.scala index b02715a6ee..5e7bae141b 100644 --- a/src/test/scala/org/ergoplatform/utils/Stubs.scala +++ b/src/test/scala/org/ergoplatform/utils/Stubs.scala @@ -342,7 +342,8 @@ trait Stubs extends ErgoGenerators with ErgoTestHelpers with ChainGenerator with val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(stateType, verifyTransactions, blocksToKeep, PoPoWBootstrap, minimalSuffix, mining = false, txCostLimit, txSizeLimit, useExternalMiner = false, internalMinersCount = 1, internalMinerPollingInterval = 1.second,miningPubKeyHex = None, - offlineGeneration = false, 200, 5.minutes, 100000, 1.minute, rebroadcastCount = 200, 1000000, 100) + offlineGeneration = false, 200, 5.minutes, 100000, 1.minute, rebroadcastCount = 200, 1000000, 100, adProofsSuffixLength = 112*1024 +) val scorexSettings: ScorexSettings = null val walletSettings: WalletSettings = null val chainSettings = settings.chainSettings.copy(epochLength = epochLength, useLastEpochs = useLastEpochs) From ad47f442ffe69160130177263f84f812c95b16e3 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Tue, 22 Mar 2022 14:22:24 +0300 Subject: [PATCH 03/13] Fix intialization of adProofsSuffixLength in config files refer #1658 --- src/main/resources/application.conf | 2 +- src/main/resources/testnet.conf | 2 +- src/test/resources/application.conf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 73e2a5d0c8..4fa611ee68 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -97,7 +97,7 @@ ergo { checkpoint = null # Dump ADProofs only for the suffix given during bootstrapping - dProofsSuffixLength = 114688 // 112k + adProofsSuffixLength = 114688 // 112k } cache { diff --git a/src/main/resources/testnet.conf b/src/main/resources/testnet.conf index ca9e5c9b86..7d75709df0 100644 --- a/src/main/resources/testnet.conf +++ b/src/main/resources/testnet.conf @@ -19,7 +19,7 @@ ergo { maxTransactionCost = 800000 # Dump ADProofs only for the suffix given during bootstrapping - dProofsSuffixLength = 114688 // 112k + adProofsSuffixLength = 114688 // 112k } chain { diff --git a/src/test/resources/application.conf b/src/test/resources/application.conf index 0e81d9911d..cc5196e8f0 100644 --- a/src/test/resources/application.conf +++ b/src/test/resources/application.conf @@ -58,7 +58,7 @@ ergo { headerChainDiff = 100 # Dump ADProofs only for the suffix given during bootstrapping - dProofsSuffixLength = 114688 // 112k + adProofsSuffixLength = 114688 // 112k } cache { From d034a08c00abdcd4cd2e3264d8a17661a680c4b5 Mon Sep 17 00:00:00 2001 From: jellymlg Date: Fri, 24 Jun 2022 17:22:51 +0200 Subject: [PATCH 04/13] Find emission box by its NFT --- .../ergoplatform/nodeView/state/UtxoStateReader.scala | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala index 20c3f522ff..49a2a816d3 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala @@ -80,11 +80,16 @@ trait UtxoStateReader extends ErgoStateReader with TransactionValidation { * @param fb - ergo full block * @return emission box from this block transactions */ - // todo: search by emission box NFT after EIP-27 activation height, https://github.com/ergoplatform/ergo/issues/1718 protected[state] def extractEmissionBox(fb: ErgoFullBlock): Option[ErgoBox] = { + def hasEmissionBox(tx: ErgoTransaction): Boolean = + if(fb.height > constants.settings.chainSettings.reemission.activationHeight) // after EIP-27 + tx.outputs.size == 2 && java.util.Arrays.equals(tx.outputs.head.additionalTokens(0)._1, constants.settings.chainSettings.reemission.emissionNftIdBytes) + else + tx.outputs.head.ergoTree == constants.settings.chainSettings.monetary.emissionBoxProposition + def fullSearch(fb: ErgoFullBlock): Option[ErgoBox] = { fb.transactions - .find(_.outputs.head.ergoTree == constants.settings.chainSettings.monetary.emissionBoxProposition) + .find(hasEmissionBox) .map(_.outputs.head) .filter(_.value > 100000 * EmissionRules.CoinsInOneErgo) // to filter out possible spam } @@ -92,7 +97,7 @@ trait UtxoStateReader extends ErgoStateReader with TransactionValidation { emissionBoxIdOpt match { case Some(id) => fb.blockTransactions.txs.view.reverse.find(_.inputs.exists(t => java.util.Arrays.equals(t.boxId, id))) match { - case Some(tx) if tx.outputs.head.ergoTree == constants.settings.chainSettings.monetary.emissionBoxProposition => + case Some(tx) if hasEmissionBox(tx) => tx.outputs.headOption case Some(_) => log.info(s"Last possible emission box consumed") From 28b84ee724f1cdaecdb9ed20721ec82e3fd1cc26 Mon Sep 17 00:00:00 2001 From: fanta <39315532+jellymlg@users.noreply.github.com> Date: Mon, 18 Jul 2022 02:09:31 +0200 Subject: [PATCH 05/13] added extra check --- .../org/ergoplatform/nodeView/state/UtxoStateReader.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala index 49a2a816d3..81e6e8b470 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala @@ -83,7 +83,9 @@ trait UtxoStateReader extends ErgoStateReader with TransactionValidation { protected[state] def extractEmissionBox(fb: ErgoFullBlock): Option[ErgoBox] = { def hasEmissionBox(tx: ErgoTransaction): Boolean = if(fb.height > constants.settings.chainSettings.reemission.activationHeight) // after EIP-27 - tx.outputs.size == 2 && java.util.Arrays.equals(tx.outputs.head.additionalTokens(0)._1, constants.settings.chainSettings.reemission.emissionNftIdBytes) + tx.outputs.size == 2 && + !tx.outputs.head.additionalTokens.isEmpty && + java.util.Arrays.equals(tx.outputs.head.additionalTokens(0)._1, constants.settings.chainSettings.reemission.emissionNftIdBytes) else tx.outputs.head.ergoTree == constants.settings.chainSettings.monetary.emissionBoxProposition From 13d0124b022c292b5f156d9966de3b247c6daf4a Mon Sep 17 00:00:00 2001 From: Alex Chepurnoy Date: Sat, 30 Jul 2022 20:57:42 +0300 Subject: [PATCH 06/13] 4.0.37 version set --- README.md | 2 +- src/main/resources/api/openapi.yaml | 2 +- src/main/resources/application.conf | 2 +- src/main/resources/mainnet.conf | 2 +- src/main/resources/testnet.conf | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 83aed14e54..4f89a0aa97 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ To run specific Ergo version `` as a service with custom config `/path/ -e MAX_HEAP=3G \ ergoplatform/ergo: -- -c /etc/myergo.conf -Available versions can be found on [Ergo Docker image page](https://hub.docker.com/r/ergoplatform/ergo/tags), for example, `v4.0.36`. +Available versions can be found on [Ergo Docker image page](https://hub.docker.com/r/ergoplatform/ergo/tags), for example, `v4.0.37`. This will connect to the Ergo mainnet or testnet following your configuration passed in `myergo.conf` and network flag `--`. Every default config value would be overwritten with corresponding value in `myergo.conf`. `MAX_HEAP` variable can be used to control how much memory can the node consume. diff --git a/src/main/resources/api/openapi.yaml b/src/main/resources/api/openapi.yaml index 5a158159ce..49f776fcee 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: "4.0.36" + version: "4.0.37" 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 5bd1d0bc48..df30b073b0 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -391,7 +391,7 @@ scorex { nodeName = "ergo-node" # Network protocol version to be sent in handshakes - appVersion = 4.0.36 + appVersion = 4.0.37 # 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 b58dde2ff1..58f63949b2 100644 --- a/src/main/resources/mainnet.conf +++ b/src/main/resources/mainnet.conf @@ -65,7 +65,7 @@ scorex { network { magicBytes = [1, 0, 2, 4] bindAddress = "0.0.0.0:9030" - nodeName = "ergo-mainnet-4.0.36" + nodeName = "ergo-mainnet-4.0.37" nodeName = ${?NODENAME} knownPeers = [ "213.239.193.208:9030", diff --git a/src/main/resources/testnet.conf b/src/main/resources/testnet.conf index 8f06e53e70..50a06e39f9 100644 --- a/src/main/resources/testnet.conf +++ b/src/main/resources/testnet.conf @@ -77,7 +77,7 @@ scorex { network { magicBytes = [2, 0, 0, 2] bindAddress = "0.0.0.0:9020" - nodeName = "ergo-testnet-4.0.36" + nodeName = "ergo-testnet-4.0.37" nodeName = ${?NODENAME} knownPeers = [ "213.239.193.208:9020", From 5eff3fda57b90708c65fa5b9368931e2801d3c73 Mon Sep 17 00:00:00 2001 From: Alex Chepurnoy Date: Thu, 4 Aug 2022 15:21:31 +0300 Subject: [PATCH 07/13] forkOrdered externalized --- src/main/resources/testnet.conf | 27 +++++++----- .../mining/CandidateGenerator.scala | 42 +++++++++++++------ 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/main/resources/testnet.conf b/src/main/resources/testnet.conf index 7e5ba2988a..fd4005404d 100644 --- a/src/main/resources/testnet.conf +++ b/src/main/resources/testnet.conf @@ -31,10 +31,12 @@ ergo { # Length of an epoch in difficulty recalculation. 1 means difficulty recalculation every block epochLength = 128 + blockInterval = 5s + # Monetary config for chain monetary { # delay between the block mined and time when the reward can be spend - minerRewardDelay = 72 + minerRewardDelay = 720 } voting { @@ -54,7 +56,7 @@ ergo { } reemission { - checkReemissionRules = true + checkReemissionRules = false emissionNftId = "06f29034fb69b23d519f84c4811a19694b8cdc2ce076147aaa050276f0b840f4" @@ -62,15 +64,15 @@ ergo { reemissionNftId = "06f2c3adfe52304543f7b623cc3fccddc0174a7db52452fef8e589adacdfdfee" - activationHeight = 188001 + activationHeight = 1880001 - reemissionStartHeight = 186400 + reemissionStartHeight = 1860400 injectionBoxBytesEncoded = "a0f9e1b5fb011003040005808098f4e9b5ca6a0402d1ed91c1b2a4730000730193c5a7c5b2a4730200f6ac0b0201345f0ed87b74008d1c46aefd3e7ad6ee5909a2324f2899031cdfee3cc1e02280808cfaf49aa53506f29034fb69b23d519f84c4811a19694b8cdc2ce076147aaa050276f0b840f40100325c3679e7e0e2f683e4a382aa74c2c1cb989bb6ad6a1d4b1c5a021d7b410d0f00" } # Base16 representation of genesis state roothash - genesisStateDigestHex = "21660785f08767ef2b5f311827e896a4b59c9d39b8f036d71af1e9c7f02120de02" + genesisStateDigestHex = "cb63aa99a3060f341781d8662b58bf18b9ad258db4fe88d09f8f71cb668cad4502" } wallet.secretStorage.secretDir = ${ergo.directory}"/wallet/keystore" @@ -78,16 +80,19 @@ ergo { scorex { network { - magicBytes = [2, 0, 0, 2] - bindAddress = "0.0.0.0:9020" - nodeName = "ergo-testnet-4.0.37" + magicBytes = [2, 0, 0, 3] + bindAddress = "0.0.0.0:9021" + nodeName = "ergo-testnet-5.0" nodeName = ${?NODENAME} knownPeers = [ - "213.239.193.208:9020", - "176.9.15.237:9020" + "213.239.193.208:9021", + "176.9.15.237:9021" ] } restApi { - apiKeyHash = null + # Hex-encoded Blake2b256 hash of an API key. Should be 64-chars long Base16 string. + # Below is the hash of "hello" string. + # Change it! + apiKeyHash = "324dcf027dd4a30a932c441f365a25e86b173defa4b8e58948253471b81b72cf" } } \ No newline at end of file diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala index d8fdbbfb88..5635f68379 100644 --- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala +++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala @@ -19,7 +19,7 @@ import org.ergoplatform.nodeView.history.ErgoHistory.Height import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader} import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader import org.ergoplatform.nodeView.state.{ErgoState, ErgoStateContext, StateType, UtxoStateReader} -import org.ergoplatform.settings.{ErgoSettings, ErgoValidationSettingsUpdate} +import org.ergoplatform.settings.{ErgoSettings, ErgoValidationSettingsUpdate, Parameters} import org.ergoplatform.wallet.Constants.MaxAssetsPerBox import org.ergoplatform.wallet.interpreter.ErgoInterpreter import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoScriptPredef, Input} @@ -378,6 +378,30 @@ object CandidateGenerator extends ScorexLogging { } } + /** + * Private method which suggests to vote for soft-fork (or not) + * + * @param ergoSettings - constant settings + * @param currentParams - network parameters after last block mined + * @param header - last mined header + * @return `true` if the node should vote for soft-fork + */ + private def forkOrdered(ergoSettings: ErgoSettings, currentParams: Parameters, header: Header): Boolean = { + val nextHeight = header.height + 1 + + val protocolVersion = ergoSettings.chainSettings.protocolVersion + val betterVersion = protocolVersion > header.version + + val votingSettings = ergoSettings.chainSettings.voting + val votingFinishHeight: Option[Height] = currentParams.softForkStartingHeight + .map(_ + votingSettings.votingLength * votingSettings.softForkEpochs) + val forkVotingAllowed = votingFinishHeight.forall(fh => nextHeight < fh) + + betterVersion && + forkVotingAllowed && + (ergoSettings.votingTargets.softFork != 0 && nextHeight >= 4096) + } + /** * Assemble correct block candidate based on * @@ -431,26 +455,20 @@ object CandidateGenerator extends ScorexLogging { .map { header => val newHeight = header.height + 1 val currentParams = stateContext.currentParameters - val betterVersion = ergoSettings.chainSettings.protocolVersion > header.version - val votingFinishHeight: Option[Height] = currentParams.softForkStartingHeight - .map(_ + votingSettings.votingLength * votingSettings.softForkEpochs) - val forkVotingAllowed = votingFinishHeight.forall(fh => newHeight < fh) - val forkOrdered = ergoSettings.votingTargets.softFork != 0 - val voteForFork = betterVersion && forkOrdered && forkVotingAllowed + val voteForSoftFork = forkOrdered(ergoSettings, currentParams, header) if (newHeight % votingSettings.votingLength == 0 && newHeight > 0) { val (newParams, activatedUpdate) = currentParams.update( newHeight, - voteForFork, + voteForSoftFork, stateContext.votingData.epochVotes, proposedUpdate, votingSettings ) - val newValidationSettings = - stateContext.validationSettings.updated(activatedUpdate) + val newValidationSettings = stateContext.validationSettings.updated(activatedUpdate) ( newParams.toExtensionCandidate ++ interlinksExtension ++ newValidationSettings.toExtensionCandidate, - newParams.suggestVotes(ergoSettings.votingTargets.targets, voteForFork), + newParams.suggestVotes(ergoSettings.votingTargets.targets, voteForSoftFork), newParams.blockVersion ) } else { @@ -459,7 +477,7 @@ object CandidateGenerator extends ScorexLogging { currentParams.vote( ergoSettings.votingTargets.targets, stateContext.votingData.epochVotes, - voteForFork + voteForSoftFork ), currentParams.blockVersion ) From 2f9f3706b0c8046c1a08b398559a3958c6a0a4ba Mon Sep 17 00:00:00 2001 From: Alex Chepurnoy Date: Thu, 4 Aug 2022 15:32:17 +0300 Subject: [PATCH 08/13] mainnet voting rules --- .../ergoplatform/mining/CandidateGenerator.scala | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala index 5635f68379..60637855ce 100644 --- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala +++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala @@ -390,16 +390,28 @@ object CandidateGenerator extends ScorexLogging { val nextHeight = header.height + 1 val protocolVersion = ergoSettings.chainSettings.protocolVersion - val betterVersion = protocolVersion > header.version + + // if protocol version is 2 (node version 4.x, we still can vote for 5.0 soft-fork) + val betterVersion = if(ergoSettings.networkType.isMainNet && protocolVersion == 2) { + true + } else { + protocolVersion > header.version + } val votingSettings = ergoSettings.chainSettings.voting val votingFinishHeight: Option[Height] = currentParams.softForkStartingHeight .map(_ + votingSettings.votingLength * votingSettings.softForkEpochs) val forkVotingAllowed = votingFinishHeight.forall(fh => nextHeight < fh) + val nextHeightCondition = if(ergoSettings.networkType.isMainNet) { + nextHeight >= 819201 // mainnet voting start height + } else { + nextHeight >= 4096 + } + betterVersion && forkVotingAllowed && - (ergoSettings.votingTargets.softFork != 0 && nextHeight >= 4096) + (ergoSettings.votingTargets.softFork != 0 && nextHeightCondition) } /** From 517dc299926eac97ef222d0bf62fd39a7001c996 Mon Sep 17 00:00:00 2001 From: Alex Chepurnoy Date: Fri, 5 Aug 2022 11:09:43 +0300 Subject: [PATCH 09/13] comment improved --- src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala index 60637855ce..947c1c4f47 100644 --- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala +++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala @@ -404,7 +404,7 @@ object CandidateGenerator extends ScorexLogging { val forkVotingAllowed = votingFinishHeight.forall(fh => nextHeight < fh) val nextHeightCondition = if(ergoSettings.networkType.isMainNet) { - nextHeight >= 819201 // mainnet voting start height + nextHeight >= 819201 // mainnet voting start height, first block of epoch #800 } else { nextHeight >= 4096 } From 72ec14eb7b46a94b7916ba40b2c2ee78873fa54f Mon Sep 17 00:00:00 2001 From: Alex Chepurnoy Date: Fri, 5 Aug 2022 15:57:24 +0300 Subject: [PATCH 10/13] close #1782: extracting header from sync info only once --- .../network/ErgoNodeViewSynchronizer.scala | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala b/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala index d36d3b0ecb..1ed52af921 100644 --- a/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala +++ b/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala @@ -324,18 +324,24 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef, } } + /** + * Variable which is caching height of last header which was extracted from sync info message + */ + private var lastSyncHeaderApplied: Option[Int] = Option.empty + /** * Calculates new continuation header from syncInfo message if any, validates it and sends it * to nodeViewHolder as a remote modifier for it to be applied * @param syncInfo other's node sync info */ - private def applyValidContinuationHeaderV2(syncInfo: ErgoSyncInfoV2, history: ErgoHistory, peer: ConnectedPeer): Unit = + private def applyValidContinuationHeaderV2(syncInfo: ErgoSyncInfoV2, + history: ErgoHistory, + peer: ConnectedPeer): Unit = { history.continuationHeaderV2(syncInfo).foreach { continuationHeader => - history.applicableTry(continuationHeader) match { - case Failure(e) if e.isInstanceOf[MalformedModifierError] => - log.warn(s"Header from syncInfoV2 ${continuationHeader.encodedId} is invalid", e) - case _ => + if (deliveryTracker.status(modifierId, modifierTypeId, Seq.empty) == ModifiersStatus.Unknown) { + if (continuationHeader.height > lastSyncHeaderApplied.getOrElse(0)) { log.info(s"Applying valid syncInfoV2 header ${continuationHeader.encodedId}") + lastSyncHeaderApplied = Some(continuationHeader.height) viewHolderRef ! ModifiersFromRemote(Seq(continuationHeader)) val modifiersToDownload = history.requiredModifiersForHeader(continuationHeader) modifiersToDownload.foreach { @@ -345,8 +351,10 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef, requestBlockSection(modifierTypeId, Seq(modifierId), peer) } } + } } } + } /** * Headers should be downloaded from an Older node, it is triggered by received sync message from an older node From ed496ca2f6ac03e13576b65ac5054bf704ceb5af Mon Sep 17 00:00:00 2001 From: Alex Chepurnoy Date: Fri, 5 Aug 2022 17:44:49 +0300 Subject: [PATCH 11/13] compilation fix --- .../org/ergoplatform/network/ErgoNodeViewSynchronizer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala b/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala index 1ed52af921..09f1a171b0 100644 --- a/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala +++ b/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala @@ -338,7 +338,7 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef, history: ErgoHistory, peer: ConnectedPeer): Unit = { history.continuationHeaderV2(syncInfo).foreach { continuationHeader => - if (deliveryTracker.status(modifierId, modifierTypeId, Seq.empty) == ModifiersStatus.Unknown) { + if (deliveryTracker.status(continuationHeader.id, Header.modifierTypeId, Seq.empty) == ModifiersStatus.Unknown) { if (continuationHeader.height > lastSyncHeaderApplied.getOrElse(0)) { log.info(s"Applying valid syncInfoV2 header ${continuationHeader.encodedId}") lastSyncHeaderApplied = Some(continuationHeader.height) From e46a3b7497bc6c28a201eaf0a34a1c55b5c5c7ef Mon Sep 17 00:00:00 2001 From: Alex Chepurnoy Date: Sat, 6 Aug 2022 22:14:17 +0300 Subject: [PATCH 12/13] improving comments --- src/main/resources/application.conf | 2 ++ .../nodeView/state/UtxoStateReader.scala | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 8a8bba561b..0f7b70441f 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -17,6 +17,8 @@ ergo { # Number of last blocks to keep with transactions and ADproofs, for all other blocks only header will be stored. # Keep all blocks from genesis if negative + # Please do not set it more than 114,688 (default adProofsSuffixLength), + # otherwise, it could be hard to find proofs around the peers blocksToKeep = -1 # Download PoPoW proof on node bootstrap diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala index 81e6e8b470..8a7564f32e 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala @@ -82,12 +82,14 @@ trait UtxoStateReader extends ErgoStateReader with TransactionValidation { */ protected[state] def extractEmissionBox(fb: ErgoFullBlock): Option[ErgoBox] = { def hasEmissionBox(tx: ErgoTransaction): Boolean = - if(fb.height > constants.settings.chainSettings.reemission.activationHeight) // after EIP-27 - tx.outputs.size == 2 && - !tx.outputs.head.additionalTokens.isEmpty && - java.util.Arrays.equals(tx.outputs.head.additionalTokens(0)._1, constants.settings.chainSettings.reemission.emissionNftIdBytes) - else + if(fb.height > constants.settings.chainSettings.reemission.activationHeight) { + // after EIP-27 we search for emission box NFT for efficiency's sake + tx.outputs.size == 2 && + !tx.outputs.head.additionalTokens.isEmpty && + java.util.Arrays.equals(tx.outputs.head.additionalTokens(0)._1, constants.settings.chainSettings.reemission.emissionNftIdBytes) + } else { tx.outputs.head.ergoTree == constants.settings.chainSettings.monetary.emissionBoxProposition + } def fullSearch(fb: ErgoFullBlock): Option[ErgoBox] = { fb.transactions From d41b64c467972b0ae8b03a22ddc69cd5ee80d088 Mon Sep 17 00:00:00 2001 From: Alex Chepurnoy Date: Sun, 7 Aug 2022 23:43:07 +0300 Subject: [PATCH 13/13] set mainnet voting height to 823297 --- .../org/ergoplatform/mining/CandidateGenerator.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala index 947c1c4f47..6808ea1e11 100644 --- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala +++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala @@ -392,7 +392,7 @@ object CandidateGenerator extends ScorexLogging { val protocolVersion = ergoSettings.chainSettings.protocolVersion // if protocol version is 2 (node version 4.x, we still can vote for 5.0 soft-fork) - val betterVersion = if(ergoSettings.networkType.isMainNet && protocolVersion == 2) { + val betterVersion = if (ergoSettings.networkType.isMainNet && protocolVersion == 2) { true } else { protocolVersion > header.version @@ -403,14 +403,14 @@ object CandidateGenerator extends ScorexLogging { .map(_ + votingSettings.votingLength * votingSettings.softForkEpochs) val forkVotingAllowed = votingFinishHeight.forall(fh => nextHeight < fh) - val nextHeightCondition = if(ergoSettings.networkType.isMainNet) { - nextHeight >= 819201 // mainnet voting start height, first block of epoch #800 + val nextHeightCondition = if (ergoSettings.networkType.isMainNet) { + nextHeight >= 823297 // mainnet voting start height, first block of epoch #804 } else { nextHeight >= 4096 } betterVersion && - forkVotingAllowed && + forkVotingAllowed && (ergoSettings.votingTargets.softFork != 0 && nextHeightCondition) }