Skip to content

Commit

Permalink
Correctly calculate hit source in tests (#3771)
Browse files Browse the repository at this point in the history
  • Loading branch information
xrtm000 authored Nov 16, 2022
1 parent 00ab821 commit f2fd9d9
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,7 @@ class BlockchainUpdatesSpec extends FreeSpec with WithBUDomain with ScalaFutures
}
}

"should survive invalid rollback" in withDomainAndRepo(
SettingsFromDefaultConfig.copy(dbSettings = SettingsFromDefaultConfig.dbSettings.copy(maxRollbackDepth = 0))
) { (d, repo) =>
"should survive invalid rollback" in withDomainAndRepo(RideV6.copy(dbSettings = dbSettings.copy(maxRollbackDepth = 0))) { (d, repo) =>
for (_ <- 1 to 10) d.appendBlock()
intercept[RuntimeException](d.rollbackTo(1)) // Should fail
d.appendBlock()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.wavesplatform.api.common

import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils._
import com.wavesplatform.common.utils.*
import com.wavesplatform.db.WithDomain
import com.wavesplatform.db.WithState.AddrWithBalance
import com.wavesplatform.features.BlockchainFeatures
Expand All @@ -10,7 +10,10 @@ import com.wavesplatform.lang.v1.compiler.TestCompiler
import com.wavesplatform.lang.v1.traits.domain.{Lease, Recipient}
import com.wavesplatform.settings.TestFunctionalitySettings
import com.wavesplatform.state.{DataEntry, Diff, EmptyDataEntry, StringDataEntry, diffs}
import com.wavesplatform.test.DomainPresets.RideV4
import com.wavesplatform.test.FreeSpec
import com.wavesplatform.transaction.TxHelpers.data
import com.wavesplatform.transaction.TxVersion.V2
import com.wavesplatform.transaction.{DataTransaction, GenesisTransaction, TxHelpers}
import com.wavesplatform.{BlocksTransactionsHelpers, history}
import monix.execution.Scheduler.Implicits.global
Expand All @@ -23,47 +26,29 @@ class CommonAccountApiSpec extends FreeSpec with WithDomain with BlocksTransacti
val entry2 = StringDataEntry("test1", "test")
val entry3 = StringDataEntry("test2", "test")

val preconditions = for {
acc <- accountGen
ts = System.currentTimeMillis()
fee <- smallFeeGen
genesis = GenesisTransaction.create(acc.toAddress, diffs.ENOUGH_AMT, ts).explicitGet()
data1 = DataTransaction.selfSigned(1.toByte, acc, Seq(entry1), fee, ts).explicitGet()
data2 = DataTransaction.selfSigned(1.toByte, acc, Seq(entry2), fee, ts).explicitGet()
data3 = DataTransaction.selfSigned(1.toByte, acc, Seq(entry3), fee, ts).explicitGet()
data4 = DataTransaction.selfSigned(2.toByte, acc, Seq(EmptyDataEntry("test"), EmptyDataEntry("test1")), fee, ts).explicitGet()
data5 = DataTransaction.selfSigned(2.toByte, acc, Seq(EmptyDataEntry("test2"), entry1, entry2), fee, ts).explicitGet()
(block1, mbs1) = UnsafeBlocks.unsafeChainBaseAndMicro(history.randomSig, Seq(genesis), Seq(Seq(data1)), acc, 3, ts)
(block2, mbs2) = UnsafeBlocks.unsafeChainBaseAndMicro(mbs1.last.totalResBlockSig, Seq(data2), Seq(Seq(data3)), acc, 3, ts)
(block3, mbs3) = UnsafeBlocks.unsafeChainBaseAndMicro(mbs2.last.totalResBlockSig, Seq(data4), Seq(Seq(data5)), acc, 3, ts)
} yield (acc, block1, mbs1.head, block2, mbs2.head, block3, mbs3.head)

forAll(preconditions) {
case (acc, block1, mb1, block2, mb2, block3, mb3) =>
withDomain(
domainSettingsWithFS(
TestFunctionalitySettings.withFeatures(
BlockchainFeatures.NG,
BlockchainFeatures.DataTransaction,
BlockchainFeatures.BlockV5
)
)
) { d =>
val commonAccountsApi = CommonAccountsApi(() => d.blockchainUpdater.bestLiquidDiff.getOrElse(Diff.empty), d.db, d.blockchainUpdater)
def dataList(): Set[DataEntry[_]] = commonAccountsApi.dataStream(acc.toAddress, None).toListL.runSyncUnsafe().toSet

d.appendBlock(block1)
d.appendMicroBlock(mb1)
dataList() shouldBe Set(entry1)
d.appendBlock(block2)
dataList() shouldBe Set(entry1, entry2)
d.appendMicroBlock(mb2)
dataList() shouldBe Set(entry1, entry2, entry3)
d.appendBlock(block3)
dataList() shouldBe Set(entry3)
d.appendMicroBlock(mb3)
dataList() shouldBe Set(entry1, entry2)
}
val acc = accountGen.sample.get
val genesis = TxHelpers.genesis(acc.toAddress)
val data1 = data(acc, Seq(entry1))
val data2 = data(acc, Seq(entry2))
val data3 = data(acc, Seq(entry3))
val data4 = data(acc, Seq(EmptyDataEntry("test"), EmptyDataEntry("test1")), version = V2)
val data5 = data(acc, Seq(EmptyDataEntry("test2"), entry1, entry2), version = V2)

withDomain(RideV4) { d =>
val commonAccountsApi = CommonAccountsApi(() => d.blockchainUpdater.bestLiquidDiff.getOrElse(Diff.empty), d.db, d.blockchainUpdater)
def dataList(): Set[DataEntry[_]] = commonAccountsApi.dataStream(acc.toAddress, None).toListL.runSyncUnsafe().toSet

d.appendBlock(genesis)
d.appendMicroBlock(data1)
dataList() shouldBe Set(entry1)
d.appendBlock(data2)
dataList() shouldBe Set(entry1, entry2)
d.appendMicroBlock(data3)
dataList() shouldBe Set(entry1, entry2, entry3)
d.appendBlock(data4)
dataList() shouldBe Set(entry3)
d.appendMicroBlock(data5)
dataList() shouldBe Set(entry1, entry2)
}
}

Expand All @@ -84,21 +69,20 @@ class CommonAccountApiSpec extends FreeSpec with WithDomain with BlocksTransacti
(block2, mbs2) = UnsafeBlocks.unsafeChainBaseAndMicro(mbs1.last.totalResBlockSig, Seq(data2), Seq(Seq(data3)), acc, 3, ts)
} yield (acc, block1, mbs1.head, block2, mbs2.head)

forAll(preconditions) {
case (acc, block1, mb1, block2, mb2) =>
withDomain(domainSettingsWithFS(TestFunctionalitySettings.withFeatures(BlockchainFeatures.NG, BlockchainFeatures.DataTransaction))) { d =>
val commonAccountsApi = CommonAccountsApi(() => d.blockchainUpdater.bestLiquidDiff.getOrElse(Diff.empty), d.db, d.blockchainUpdater)
def dataList(): Set[DataEntry[_]] = commonAccountsApi.dataStream(acc.toAddress, Some("test_.*")).toListL.runSyncUnsafe().toSet

d.appendBlock(block1)
dataList() shouldBe empty
d.appendMicroBlock(mb1)
dataList() shouldBe Set(entry1)
d.appendBlock(block2)
dataList() shouldBe Set(entry1)
d.appendMicroBlock(mb2)
dataList() shouldBe Set(entry1, entry3)
}
forAll(preconditions) { case (acc, block1, mb1, block2, mb2) =>
withDomain(domainSettingsWithFS(TestFunctionalitySettings.withFeatures(BlockchainFeatures.NG, BlockchainFeatures.DataTransaction))) { d =>
val commonAccountsApi = CommonAccountsApi(() => d.blockchainUpdater.bestLiquidDiff.getOrElse(Diff.empty), d.db, d.blockchainUpdater)
def dataList(): Set[DataEntry[_]] = commonAccountsApi.dataStream(acc.toAddress, Some("test_.*")).toListL.runSyncUnsafe().toSet

d.appendBlock(block1)
dataList() shouldBe empty
d.appendMicroBlock(mb1)
dataList() shouldBe Set(entry1)
d.appendBlock(block2)
dataList() shouldBe Set(entry1)
d.appendMicroBlock(mb2)
dataList() shouldBe Set(entry1, entry3)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package com.wavesplatform.history

import com.wavesplatform.account.KeyPair
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.crypto._
import com.wavesplatform.features.BlockchainFeatures
import com.wavesplatform.history.Domain.BlockchainUpdaterExt
import com.wavesplatform.settings.{BlockchainSettings, WavesSettings}
import com.wavesplatform.state._
import com.wavesplatform.state.diffs._
import com.wavesplatform.test._
import com.wavesplatform.state.*
import com.wavesplatform.state.diffs.*
import com.wavesplatform.test.*
import com.wavesplatform.transaction.Asset.Waves
import com.wavesplatform.transaction.assets.{IssueTransaction, SponsorFeeTransaction}
import com.wavesplatform.transaction.transfer._
import com.wavesplatform.transaction.transfer.*
import com.wavesplatform.transaction.{Asset, GenesisTransaction}
import org.scalacheck.Gen

class BlockchainUpdaterSponsoredFeeBlockTest extends PropSpec with DomainScenarioDrivenPropertyCheck {
private val time = new TestTime
private def ts = time.getTimestamp()

private val amtTx = 100000

Expand All @@ -26,7 +26,6 @@ class BlockchainUpdaterSponsoredFeeBlockTest extends PropSpec with DomainScenari
val sponsorPreconditions: Gen[Setup] = for {

master <- accountGen
ts <- timestampGen
transferAssetWavesFee <- smallFeeGen
_ <- accountGen
alice <- accountGen
Expand Down Expand Up @@ -90,33 +89,29 @@ class BlockchainUpdaterSponsoredFeeBlockTest extends PropSpec with DomainScenari

val SponsoredFeeActivatedAt0BlockchainSettings: BlockchainSettings = DefaultBlockchainSettings.copy(
functionalitySettings = DefaultBlockchainSettings.functionalitySettings
.copy(featureCheckBlocksPeriod = 1, blocksForFeatureActivation = 1, preActivatedFeatures = Map(
.copy(
featureCheckBlocksPeriod = 1,
blocksForFeatureActivation = 1,
preActivatedFeatures = Map(
BlockchainFeatures.FeeSponsorship.id -> 0,
BlockchainFeatures.NG.id -> 0,
BlockchainFeatures.BlockV5.id -> 0
))
)
)
)

val SponsoredActivatedAt0WavesSettings: WavesSettings = settings.copy(blockchainSettings = SponsoredFeeActivatedAt0BlockchainSettings)

property("not enough waves to sponsor sponsored tx") {
scenario(sponsorPreconditions, SponsoredActivatedAt0WavesSettings) {
case (domain, (genesis, masterToAlice, feeAsset, sponsor, aliceToBob, bobToMaster, bobToMaster2)) =>
val (block0, microBlocks) = chainBaseAndMicro(randomSig, genesis, Seq(masterToAlice, feeAsset, sponsor).map(Seq(_)))
val block1 =
customBuildBlockOfTxs(microBlocks.last.totalResBlockSig, Seq.empty, KeyPair(Array.fill(KeyLength)(1: Byte)), 3: Byte, sponsor.timestamp + 1)
val block2 = customBuildBlockOfTxs(block1.id(), Seq.empty, KeyPair(Array.fill(KeyLength)(1: Byte)), 3: Byte, sponsor.timestamp + 1)
val block3 = buildBlockOfTxs(block2.id(), Seq(aliceToBob, bobToMaster))
val block4 = buildBlockOfTxs(block3.id(), Seq(bobToMaster2))

domain.blockchainUpdater.processBlock(block0) should beRight
domain.blockchainUpdater.processMicroBlock(microBlocks(0)) should beRight
domain.blockchainUpdater.processMicroBlock(microBlocks(1)) should beRight
domain.blockchainUpdater.processMicroBlock(microBlocks(2)) should beRight
domain.blockchainUpdater.processBlock(block1) should beRight
domain.blockchainUpdater.processBlock(block2) should beRight
domain.blockchainUpdater.processBlock(block3) should beRight
domain.blockchainUpdater.processBlock(block4) should produce("negative waves balance" /*"unavailable funds"*/ )
case (d, (genesis, masterToAlice, feeAsset, sponsor, aliceToBob, bobToMaster, bobToMaster2)) =>
d.appendBlock(genesis)
d.appendBlock()
d.appendMicroBlock(masterToAlice)
d.appendMicroBlock(feeAsset)
d.appendMicroBlock(sponsor)
d.appendBlock(aliceToBob, bobToMaster)
d.appendBlockE(bobToMaster2) should produce("negative waves balance" /*"unavailable funds"*/ )
}
}

Expand Down
34 changes: 25 additions & 9 deletions node/src/test/scala/com/wavesplatform/history/Domain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.wavesplatform.consensus.nxt.NxtLikeConsensusBlockData
import com.wavesplatform.consensus.{PoSCalculator, PoSSelector}
import com.wavesplatform.database.{DBExt, Keys, LevelDBWriter}
import com.wavesplatform.events.BlockchainUpdateTriggers
import com.wavesplatform.features.BlockchainFeatures.{BlockV5, RideV6}
import com.wavesplatform.lagonaki.mocks.TestBlock
import com.wavesplatform.lang.ValidationError
import com.wavesplatform.lang.script.Script
Expand All @@ -23,7 +24,7 @@ import com.wavesplatform.transaction.{BlockchainUpdater, *}
import com.wavesplatform.utils.{EthEncoding, SystemTime}
import com.wavesplatform.utx.UtxPoolImpl
import com.wavesplatform.wallet.Wallet
import com.wavesplatform.{Application, TestValues, database}
import com.wavesplatform.{Application, TestValues, crypto, database}
import monix.execution.Scheduler.Implicits.global
import org.iq80.leveldb.DB
import org.scalatest.matchers.should.Matchers.*
Expand Down Expand Up @@ -53,7 +54,7 @@ case class Domain(db: DB, blockchainUpdater: BlockchainUpdaterImpl, levelDBWrite

lazy val utxPool: UtxPoolImpl =
new UtxPoolImpl(SystemTime, blockchain, settings.utxSettings, settings.maxTxErrorLogSize, settings.minerSettings.enable)
lazy val wallet: Wallet = Wallet(settings.walletSettings.copy(file = None))
lazy val wallet: Wallet = Wallet(settings.walletSettings.copy(file = None))

object commonApi {

Expand Down Expand Up @@ -220,12 +221,15 @@ case class Domain(db: DB, blockchainUpdater: BlockchainUpdaterImpl, levelDBWrite
def appendBlockE(txs: Transaction*): Either[ValidationError, Seq[Diff]] =
appendBlockE(createBlock(Block.PlainBlockVersion, txs))

def appendBlock(txs: Transaction*): Block = {
val block = createBlock(Block.PlainBlockVersion, txs)
def appendBlock(version: Byte, txs: Transaction*): Block = {
val block = createBlock(version, txs)
appendBlock(block)
lastBlock
}

def appendBlock(txs: Transaction*): Block =
appendBlock(Block.PlainBlockVersion, txs: _*)

def appendKeyBlock(ref: Option[ByteStr] = None): Block = {
val block = createBlock(Block.NgBlockVersion, Nil, ref.orElse(Some(lastBlockId)))
val discardedDiffs = appendBlock(block)
Expand All @@ -237,7 +241,7 @@ case class Domain(db: DB, blockchainUpdater: BlockchainUpdaterImpl, levelDBWrite
def appendMicroBlockE(txs: Transaction*): Either[Throwable, BlockId] =
Try(appendMicroBlock(txs*)).toEither

def appendMicroBlock(txs: Transaction*): BlockId = {
def createMicroBlock(txs: Transaction*): MicroBlock = {
val lastBlock = this.lastBlock
val block = Block
.buildAndSign(
Expand All @@ -252,7 +256,11 @@ case class Domain(db: DB, blockchainUpdater: BlockchainUpdaterImpl, levelDBWrite
lastBlock.header.rewardVote
)
.explicitGet()
val mb = MicroBlock.buildAndSign(lastBlock.header.version, defaultSigner, txs, blockchainUpdater.lastBlockId.get, block.signature).explicitGet()
MicroBlock.buildAndSign(lastBlock.header.version, defaultSigner, txs, blockchainUpdater.lastBlockId.get, block.signature).explicitGet()
}

def appendMicroBlock(txs: Transaction*): BlockId = {
val mb = createMicroBlock(txs: _*)
blockchainUpdater.processMicroBlock(mb).explicitGet()
}

Expand Down Expand Up @@ -406,9 +414,17 @@ case class Domain(db: DB, blockchainUpdater: BlockchainUpdaterImpl, levelDBWrite
}

object Domain {
implicit class BlockchainUpdaterExt[A <: BlockchainUpdater](bcu: A) {
def processBlock(block: Block): Either[ValidationError, Seq[Diff]] =
bcu.processBlock(block, block.header.generationSignature)
implicit class BlockchainUpdaterExt[A <: BlockchainUpdater with Blockchain](bcu: A) {
def processBlock(block: Block): Either[ValidationError, Seq[Diff]] = {
val hitSource =
if (bcu.height == 0 || !bcu.activatedFeaturesAt(bcu.height + 1).contains(BlockV5.id))
block.header.generationSignature
else {
val hs = bcu.hitSource(bcu.height).get
crypto.verifyVRF(block.header.generationSignature, hs.arr, block.header.generator, bcu.isFeatureActivated(RideV6)).explicitGet()
}
bcu.processBlock(block, hitSource)
}
}

def portfolio(address: Address, db: DB, blockchainUpdater: BlockchainUpdaterImpl): Seq[(IssuedAsset, Long)] = db.withResource { resource =>
Expand Down
31 changes: 8 additions & 23 deletions node/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.wavesplatform.mining

import java.util.concurrent.atomic.AtomicReference

import com.typesafe.config.ConfigFactory
import com.wavesplatform.account.{AddressOrAlias, KeyPair}
import com.wavesplatform.block.serialization.{BlockHeaderSerializer, BlockSerializer}
Expand Down Expand Up @@ -36,12 +34,13 @@ import org.scalacheck.Gen
import org.scalatest.*
import org.scalatest.enablers.Length

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

private val testTime = new TestTime(1)
private val testTime = TestTime(1)
def shiftTime(miner: MinerImpl, minerAcc: KeyPair): Unit = {
val offset = miner.getNextBlockGenerationOffset(minerAcc).explicitGet()
testTime.advance(offset + 1.milli)
Expand Down Expand Up @@ -392,14 +391,8 @@ class BlockV5Test extends FlatSpec with WithDomain with OptionValues with Either
d =>
def applyBlock(txs: Transaction*): SignedBlockHeader = {
d.appendBlock(
TestBlock.create(
System.currentTimeMillis(),
d.blockchainUpdater.lastBlockId.getOrElse(TestBlock.randomSignature()),
txs,
version =
if (d.blockchainUpdater.height >= 1) Block.ProtoBlockVersion
else Block.PlainBlockVersion
)
if (d.blockchainUpdater.height >= 1) Block.ProtoBlockVersion else Block.PlainBlockVersion,
txs: _*
)
lastBlock
}
Expand All @@ -419,19 +412,11 @@ class BlockV5Test extends FlatSpec with WithDomain with OptionValues with Either
block3.header.reference shouldBe block2.id()
block3.id() should have length crypto.DigestLength

val (keyBlock, microBlocks) =
UnsafeBlocks.unsafeChainBaseAndMicro(
block3.id(),
Nil,
Seq(Seq(TxHelpers.transfer()), Seq(TxHelpers.transfer())),
acc,
Block.ProtoBlockVersion,
System.currentTimeMillis()
)
d.appendBlock(keyBlock)
microBlocks.foreach(d.appendMicroBlock)
val keyBlock = d.appendKeyBlock()
val mb1 = d.createMicroBlock(TxHelpers.transfer())
d.blockchain.processMicroBlock(mb1)
d.appendMicroBlock(TxHelpers.transfer())

val mb1 = d.microBlocks.head
mb1.totalResBlockSig should have length crypto.SignatureLength
mb1.reference should not be keyBlock.signature
mb1.reference shouldBe keyBlock.id()
Expand Down
Loading

0 comments on commit f2fd9d9

Please sign in to comment.