-
Notifications
You must be signed in to change notification settings - Fork 75
/
MinerSpecSetup.scala
134 lines (110 loc) · 4.52 KB
/
MinerSpecSetup.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package io.iohk.ethereum.consensus.ethash
import akka.actor.ActorSystem
import akka.testkit.{TestActorRef, TestProbe}
import akka.util.ByteString
import io.iohk.ethereum.Fixtures
import io.iohk.ethereum.blockchain.sync.ScenarioSetup
import io.iohk.ethereum.blockchain.sync.regular.RegularSync.MinedBlock
import io.iohk.ethereum.consensus.blocks.PendingBlock
import io.iohk.ethereum.consensus.ethash.blocks.EthashBlockGenerator
import io.iohk.ethereum.consensus.ethash.difficulty.EthashDifficultyCalculator
import io.iohk.ethereum.domain._
import io.iohk.ethereum.ledger.Ledger.VMImpl
import org.bouncycastle.util.encoders.Hex
import org.scalamock.scalatest.MockFactory
import scala.concurrent.Future
import scala.concurrent.duration.{Duration, FiniteDuration}
abstract class MinerSpecSetup(implicit system: ActorSystem) extends ScenarioSetup with MockFactory {
def miner: TestActorRef[Nothing]
val origin =
Block(Fixtures.Blocks.Genesis.header, Fixtures.Blocks.Genesis.body)
val sync = TestProbe()
def waitForMinedBlock(implicit timeout: Duration): Block = {
sync.expectMsgPF[Block](timeout) {
case m: MinedBlock => m.block
}
}
def expectNoNewBlockMsg(timeout: FiniteDuration): Unit = {
sync.expectNoMessage(timeout)
}
private def calculateGasLimit(parentGas: UInt256): UInt256 = {
val GasLimitBoundDivisor: Int = 1024
val gasLimitDifference = parentGas / GasLimitBoundDivisor
parentGas + gasLimitDifference - 1
}
val blockGenerator: EthashBlockGenerator = mock[EthashBlockGenerator]
override lazy val blockchain: BlockchainImpl = mock[BlockchainImpl]
override lazy val vm: VMImpl = new VMImpl
override lazy val consensus: EthashConsensus = buildEthashConsensus().withBlockGenerator(blockGenerator)
val blockCreator = mock[EthashBlockCreator]
val difficultyCalc = new EthashDifficultyCalculator(blockchainConfig)
val blockForMiningTimestamp = System.currentTimeMillis()
val txToMine = SignedTransaction(
tx = Transaction(
nonce = BigInt("438553"),
gasPrice = BigInt("20000000000"),
gasLimit = BigInt("50000"),
receivingAddress = Address(ByteString(Hex.decode("3435be928d783b7c48a2c3109cba0d97d680747a"))),
value = BigInt("108516826677274384"),
payload = ByteString.empty
),
pointSign = 0x9d.toByte,
signatureRandom = ByteString(Hex.decode("beb8226bdb90216ca29967871a6663b56bdd7b86cf3788796b52fd1ea3606698")),
signature = ByteString(Hex.decode("2446994156bc1780cb5806e730b171b38307d5de5b9b0d9ad1f9de82e00316b5")),
chainId = 0x3d.toByte
)
def blockForMining(parentHeader: BlockHeader, transactions: Seq[SignedTransaction] = Seq(txToMine)): Block = {
Block(
BlockHeader(
parentHash = parentHeader.hash,
ommersHash = ByteString(Hex.decode("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")),
beneficiary = consensusConfig.coinbase.bytes,
stateRoot = parentHeader.stateRoot,
transactionsRoot = parentHeader.transactionsRoot,
receiptsRoot = parentHeader.receiptsRoot,
logsBloom = parentHeader.logsBloom,
difficulty = difficultyCalc.calculateDifficulty(1, blockForMiningTimestamp, parentHeader),
number = BigInt(1),
gasLimit = calculateGasLimit(UInt256(parentHeader.gasLimit)),
gasUsed = BigInt(0),
unixTimestamp = blockForMiningTimestamp,
extraData = consensusConfig.headerExtraData,
mixHash = ByteString.empty,
nonce = ByteString.empty,
treasuryOptOut = None
),
BlockBody(transactions, Nil)
)
}
val parentActor = TestProbe()
def blockCreatorBehaviour(parentBlock: Block, withTransactions: Boolean, resultBlock: Block) = {
(blockCreator
.getBlockForMining(_: Block, _: Boolean))
.expects(parentBlock, withTransactions)
.returning(
Future
.successful(PendingBlock(resultBlock, Nil))
)
.atLeastOnce()
}
def blockCreatorBehaviourExpectingInitialWorld(parentBlock: Block, withTransactions: Boolean, resultBlock: Block) = {
(blockCreator
.getBlockForMining(_: Block, _: Boolean))
.expects(where { (parent, withTxs) =>
parent == parentBlock && withTxs == withTransactions
})
.returning(
Future
.successful(PendingBlock(resultBlock, Nil))
)
.atLeastOnce()
}
def withStartedMiner(behaviour: => Unit) = {
miner ! MinerProtocol.StartMining
behaviour
miner ! MinerProtocol.StopMining
}
def sendToMiner(msg: MinerProtocol) = {
miner.tell(msg, parentActor.ref)
}
}