Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed InvalidStateHash #3937

Open
wants to merge 2 commits into
base: version-1.5.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions node/src/main/scala/com/wavesplatform/mining/Miner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,13 @@ class MinerImpl(
}
}

def forgeBlock(account: KeyPair): Either[String, (Block, MiningConstraint)] = {
def forgeBlock(account: KeyPair, referenceOpt: Option[ByteStr] = None): Either[String, (Block, MiningConstraint)] = {
// should take last block right at the time of mining since microblocks might have been added
val height = blockchainUpdater.height
val version = blockchainUpdater.nextBlockVersion
val lastBlockHeader = blockchainUpdater.lastBlockHeader.get.header
val reference = blockchainUpdater.bestLastBlockInfo(System.currentTimeMillis() - minMicroBlockDurationMills).get.blockId
val lastBlockInfo = blockchainUpdater.bestLastBlockInfo(System.currentTimeMillis() - minMicroBlockDurationMills)
val reference = referenceOpt.getOrElse(lastBlockInfo.get.blockId)

metrics.blockBuildTimeStats.measureSuccessful(for {
_ <- checkQuorumAvailable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,27 @@ class BlockchainUpdaterImpl(
.orElse(lastBlockReward)
}

def referencedBlockchain(reference: ByteStr): Blockchain =
ngState
.flatMap(ng =>
if (ng.base.header.reference == reference)
Some(SnapshotBlockchain(rocksdb, ng.reward))
else
ng.snapshotOf(reference)
.map { case (forgedBlock, liquidSnapshot, carry, _, stateHash, _) =>
SnapshotBlockchain(
rocksdb,
liquidSnapshot,
forgedBlock,
ng.hitSource,
carry,
computeNextReward,
Some(stateHash)
)
}
)
.getOrElse(SnapshotBlockchain(rocksdb, computeNextReward))

override def processBlock(
block: Block,
hitSource: ByteStr,
Expand Down Expand Up @@ -296,7 +317,8 @@ class BlockchainUpdaterImpl(
)
} else
metrics.forgeBlockTimeStats.measureOptional(ng.snapshotOf(block.header.reference)) match {
case None => Left(BlockAppendError(s"References incorrect or non-existing block", block))
case None =>
Left(BlockAppendError(s"References incorrect or non-existing block", block))
case Some((referencedForgedBlock, referencedLiquidSnapshot, carry, totalFee, referencedComputedStateHash, discarded)) =>
if (!verify || referencedForgedBlock.signatureValid()) {
val height = rocksdb.heightOf(referencedForgedBlock.header.reference).getOrElse(0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,19 +284,19 @@ object BlockDiffer {
}

def createInitialBlockSnapshot(
blockchain: BlockchainUpdater & Blockchain,
blockchainUpdater: BlockchainUpdater & Blockchain,
reference: ByteStr,
miner: Address
): Either[ValidationError, StateSnapshot] = {
val fullReward = blockchain.computeNextReward.fold(Portfolio.empty)(Portfolio.waves)
val blockchain = blockchainUpdater.referencedBlockchain(reference)
val feeFromPreviousBlock = Portfolio.waves(blockchain.carryFee(Some(reference)))

val daoAddress = blockchain.settings.functionalitySettings.daoAddressParsed.toOption.flatten
val xtnBuybackAddress = blockchain.settings.functionalitySettings.xtnBuybackAddressParsed.toOption.flatten

val rewardShares = BlockRewardCalculator.getBlockRewardShares(
blockchain.height + 1,
fullReward.balance,
blockchainUpdater.computeNextReward.getOrElse(0),
daoAddress,
xtnBuybackAddress,
blockchain
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import com.wavesplatform.block.Block.BlockId
import com.wavesplatform.block.{Block, BlockSnapshot, MicroBlock, MicroBlockSnapshot}
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.lang.ValidationError
import com.wavesplatform.state.Blockchain
import com.wavesplatform.state.BlockchainUpdaterImpl.BlockApplyResult
import monix.reactive.Observable

Expand All @@ -20,6 +21,7 @@ trait BlockchainUpdater {
def removeAfter(blockId: ByteStr): Either[ValidationError, DiscardedBlocks]
def lastBlockInfo: Observable[LastBlockInfo]
def isLastBlockId(id: ByteStr): Boolean
def referencedBlockchain(reference: ByteStr): Blockchain
def shutdown(): Unit
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import com.wavesplatform.block.{Block, BlockHeader, SignedBlockHeader}
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.crypto.DigestLength
import com.wavesplatform.db.WithDomain
import com.wavesplatform.features.BlockchainFeatures
import com.wavesplatform.history.{chainBaseAndMicro, defaultSigner}
import com.wavesplatform.lagonaki.mocks.TestBlock
Expand All @@ -28,7 +27,8 @@ import org.scalatest.enablers.Length

import java.util.concurrent.atomic.AtomicReference
import scala.concurrent.duration.*
class BlockV5Test extends FlatSpec with WithDomain with OptionValues with EitherValues with BlocksTransactionsHelpers {

class BlockV5Test extends FlatSpec with WithMiner with OptionValues with EitherValues with BlocksTransactionsHelpers {
import BlockV5Test.*

private val testTime = TestTime(1)
Expand Down
Loading