Skip to content

Commit

Permalink
Merge pull request #1787 from ergoplatform/v4.0.37
Browse files Browse the repository at this point in the history
Candidate for 4.0.37
  • Loading branch information
kushti authored Aug 7, 2022
2 parents 6a96896 + d41b64c commit 6ed3b23
Show file tree
Hide file tree
Showing 15 changed files with 116 additions and 44 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ To run specific Ergo version `<VERSION>` as a service with custom config `/path/
-e MAX_HEAP=3G \
ergoplatform/ergo:<VERSION> --<networkId> -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 `--<networkId>`. 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.

Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/api/openapi.yaml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
7 changes: 6 additions & 1 deletion src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -95,6 +97,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
adProofsSuffixLength = 114688 // 112k
}

cache {
Expand Down Expand Up @@ -391,7 +396,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.
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/mainnet.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
32 changes: 20 additions & 12 deletions src/main/resources/testnet.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
adProofsSuffixLength = 114688 // 112k
}

chain {
# Network address prefix, currently reserved values are 0 (money chain mainnet) and 16 (money chain testnet)
Expand All @@ -28,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 {
Expand All @@ -51,40 +56,43 @@ ergo {
}

reemission {
checkReemissionRules = true
checkReemissionRules = false

emissionNftId = "06f29034fb69b23d519f84c4811a19694b8cdc2ce076147aaa050276f0b840f4"

reemissionTokenId = "01345f0ed87b74008d1c46aefd3e7ad6ee5909a2324f2899031cdfee3cc1e022"

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"
}

scorex {
network {
magicBytes = [2, 0, 0, 2]
bindAddress = "0.0.0.0:9020"
nodeName = "ergo-testnet-4.0.36"
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"
}
}
54 changes: 42 additions & 12 deletions src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -378,6 +378,42 @@ 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

// 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 >= 823297 // mainnet voting start height, first block of epoch #804
} else {
nextHeight >= 4096
}

betterVersion &&
forkVotingAllowed &&
(ergoSettings.votingTargets.softFork != 0 && nextHeightCondition)
}

/**
* Assemble correct block candidate based on
*
Expand Down Expand Up @@ -431,26 +467,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 {
Expand All @@ -459,7 +489,7 @@ object CandidateGenerator extends ScorexLogging {
currentParams.vote(
ergoSettings.votingTargets.targets,
stateContext.votingData.epochVotes,
voteForFork
voteForSoftFork
),
currentParams.blockVersion
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(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)
viewHolderRef ! ModifiersFromRemote(Seq(continuationHeader))
val modifiersToDownload = history.requiredModifiersForHeader(continuationHeader)
modifiersToDownload.foreach {
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,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 " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,28 @@ 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 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
.find(_.outputs.head.ergoTree == constants.settings.chainSettings.monetary.emissionBoxProposition)
.find(hasEmissionBox)
.map(_.outputs.head)
.filter(_.value > 100000 * EmissionRules.CoinsInOneErgo) // to filter out possible spam
}

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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
/**
Expand Down Expand Up @@ -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")
)
Expand Down
3 changes: 3 additions & 0 deletions src/test/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
adProofsSuffixLength = 114688 // 112k
}

cache {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class ErgoSettingsSpecification extends ErgoPropertyTest {
mempoolCleanupDuration = 10.seconds,
rebroadcastCount = 3,
minimalFeeAmount = 0,
headerChainDiff = 100
headerChainDiff = 100,
adProofsSuffixLength = 112*1024
)
settings.cacheSettings shouldBe CacheSettings(
HistoryCacheSettings(
Expand Down Expand Up @@ -89,7 +90,8 @@ class ErgoSettingsSpecification extends ErgoPropertyTest {
mempoolCleanupDuration = 10.seconds,
rebroadcastCount = 3,
minimalFeeAmount = 0,
headerChainDiff = 100
headerChainDiff = 100,
adProofsSuffixLength = 112*1024
)
settings.cacheSettings shouldBe CacheSettings(
HistoryCacheSettings(
Expand Down Expand Up @@ -132,7 +134,8 @@ class ErgoSettingsSpecification extends ErgoPropertyTest {
mempoolCleanupDuration = 10.seconds,
rebroadcastCount = 3,
minimalFeeAmount = 0,
headerChainDiff = 100
headerChainDiff = 100,
adProofsSuffixLength = 112*1024
)
settings.cacheSettings shouldBe CacheSettings(
HistoryCacheSettings(
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/org/ergoplatform/tools/ChainGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion src/test/scala/org/ergoplatform/utils/Stubs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,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)
Expand Down

0 comments on commit 6ed3b23

Please sign in to comment.