fix EIP-4399 'random' opcode
- fix previous implementation of EIP-4399 - now `random` opcode can be used with evmc_enabled
This commit is contained in:
parent
20068de838
commit
28cdfcaf6b
|
@ -19,6 +19,7 @@ type
|
||||||
networkId*: NetworkId
|
networkId*: NetworkId
|
||||||
config* : ChainConfig
|
config* : ChainConfig
|
||||||
genesis* : Genesis
|
genesis* : Genesis
|
||||||
|
totalDifficulty*: DifficultyInt
|
||||||
|
|
||||||
# startingBlock, currentBlock, and highestBlock
|
# startingBlock, currentBlock, and highestBlock
|
||||||
# are progress indicator
|
# are progress indicator
|
||||||
|
@ -30,6 +31,16 @@ type
|
||||||
blockNumber: BlockNumber
|
blockNumber: BlockNumber
|
||||||
index: int
|
index: int
|
||||||
|
|
||||||
|
proc getTotalDifficulty*(self: BaseChainDB): UInt256 =
|
||||||
|
# this is actually a combination of `getHash` and `getScore`
|
||||||
|
const key = canonicalHeadHashKey()
|
||||||
|
let data = self.db.get(key.toOpenArray)
|
||||||
|
if data.len == 0:
|
||||||
|
return 0.u256
|
||||||
|
|
||||||
|
let blockHash = rlp.decode(data, Hash256)
|
||||||
|
rlp.decode(self.db.get(blockHashToScoreKey(blockHash).toOpenArray), Uint256)
|
||||||
|
|
||||||
proc newBaseChainDB*(
|
proc newBaseChainDB*(
|
||||||
db: TrieDatabaseRef,
|
db: TrieDatabaseRef,
|
||||||
pruneTrie: bool = true,
|
pruneTrie: bool = true,
|
||||||
|
@ -42,6 +53,7 @@ proc newBaseChainDB*(
|
||||||
result.networkId = id
|
result.networkId = id
|
||||||
result.config = params.config
|
result.config = params.config
|
||||||
result.genesis = params.genesis
|
result.genesis = params.genesis
|
||||||
|
result.totalDifficulty = result.getTotalDifficulty()
|
||||||
|
|
||||||
proc `$`*(db: BaseChainDB): string =
|
proc `$`*(db: BaseChainDB): string =
|
||||||
result = "BaseChainDB"
|
result = "BaseChainDB"
|
||||||
|
@ -335,6 +347,7 @@ proc persistHeaderToDb*(self: BaseChainDB; header: BlockHeader): seq[BlockHeader
|
||||||
return self.setAsCanonicalChainHead(headerHash)
|
return self.setAsCanonicalChainHead(headerHash)
|
||||||
|
|
||||||
if score > headScore:
|
if score > headScore:
|
||||||
|
self.totalDifficulty = score
|
||||||
result = self.setAsCanonicalChainHead(headerHash)
|
result = self.setAsCanonicalChainHead(headerHash)
|
||||||
|
|
||||||
proc persistUncles*(self: BaseChainDB, uncles: openarray[BlockHeader]): Hash256 =
|
proc persistUncles*(self: BaseChainDB, uncles: openarray[BlockHeader]): Hash256 =
|
||||||
|
|
|
@ -18,6 +18,3 @@ type
|
||||||
FkIstanbul = "Istanbul"
|
FkIstanbul = "Istanbul"
|
||||||
FkBerlin = "Berlin"
|
FkBerlin = "Berlin"
|
||||||
FkLondon = "London"
|
FkLondon = "London"
|
||||||
# TODO: PostMerge is a temporary name
|
|
||||||
# until we have an official name
|
|
||||||
FkPostMerge = "PostMerge"
|
|
||||||
|
|
|
@ -38,8 +38,7 @@ const
|
||||||
eth2, # FkPetersburg
|
eth2, # FkPetersburg
|
||||||
eth2, # FkIstanbul
|
eth2, # FkIstanbul
|
||||||
eth2, # FkBerlin
|
eth2, # FkBerlin
|
||||||
eth2, # FkLondon
|
eth2 # FkLondon
|
||||||
eth0 # FkPostMerge
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
|
@ -73,10 +73,6 @@ proc setupTxContext(host: TransactionHost) =
|
||||||
# EIP-4399
|
# EIP-4399
|
||||||
# Transfer block randomness to difficulty OPCODE
|
# Transfer block randomness to difficulty OPCODE
|
||||||
let difficulty = vmState.difficulty.toEvmc
|
let difficulty = vmState.difficulty.toEvmc
|
||||||
if difficulty.isZero:
|
|
||||||
# no flipping, because hash is a 32 bytes array
|
|
||||||
host.txContext.block_difficulty = vmState.random.toEvmc
|
|
||||||
else:
|
|
||||||
host.txContext.block_difficulty = flip256(difficulty)
|
host.txContext.block_difficulty = flip256(difficulty)
|
||||||
|
|
||||||
host.cachedTxContext = true
|
host.cachedTxContext = true
|
||||||
|
|
|
@ -66,6 +66,10 @@ type
|
||||||
limits: TxChainGasLimits ## Gas limits for packer and next header
|
limits: TxChainGasLimits ## Gas limits for packer and next header
|
||||||
txEnv: TxChainPackerEnv ## Assorted parameters, tx packer environment
|
txEnv: TxChainPackerEnv ## Assorted parameters, tx packer environment
|
||||||
|
|
||||||
|
# EIP-4399 and EIP-3675
|
||||||
|
ttdReached: bool ## Total Terminal Difficulty reached
|
||||||
|
random: Hash256 ## POS block randomness
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Private functions
|
# Private functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -79,12 +83,10 @@ proc resetTxEnv(dh: TxChainRef; parent: BlockHeader; fee: Option[UInt256])
|
||||||
timestamp = getTime().utc.toTime,
|
timestamp = getTime().utc.toTime,
|
||||||
gasLimit = (if dh.maxMode: dh.limits.maxLimit else: dh.limits.trgLimit),
|
gasLimit = (if dh.maxMode: dh.limits.maxLimit else: dh.limits.trgLimit),
|
||||||
fee = fee,
|
fee = fee,
|
||||||
# EIP-4399 extra complexity
|
random = dh.random,
|
||||||
# TODO: make sure from where or what value
|
|
||||||
# this `random` param should be
|
|
||||||
random = Hash256(),
|
|
||||||
miner = dh.miner,
|
miner = dh.miner,
|
||||||
chainDB = dh.db)
|
chainDB = dh.db,
|
||||||
|
ttdReached= dh.ttdReached)
|
||||||
|
|
||||||
dh.txEnv.txRoot = BLANK_ROOT_HASH
|
dh.txEnv.txRoot = BLANK_ROOT_HASH
|
||||||
dh.txEnv.stateRoot = dh.txEnv.vmState.parent.stateRoot
|
dh.txEnv.stateRoot = dh.txEnv.vmState.parent.stateRoot
|
||||||
|
@ -307,6 +309,14 @@ proc `txRoot=`*(dh: TxChainRef; val: Hash256) =
|
||||||
## Setter
|
## Setter
|
||||||
dh.txEnv.txRoot = val
|
dh.txEnv.txRoot = val
|
||||||
|
|
||||||
|
proc `ttdReached=`*(dh: TxChainRef; val: bool) =
|
||||||
|
## Setter
|
||||||
|
dh.ttdReached = val
|
||||||
|
|
||||||
|
proc `random=`*(dh: TxChainRef; val: Hash256) =
|
||||||
|
## Setter
|
||||||
|
dh.random = val
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -51,15 +51,6 @@ template getDifficulty*(c: Computation): DifficultyInt =
|
||||||
else:
|
else:
|
||||||
c.vmState.difficulty
|
c.vmState.difficulty
|
||||||
|
|
||||||
template getRandom*(c: Computation): Hash256 =
|
|
||||||
when evmc_enabled:
|
|
||||||
# EIP-4399
|
|
||||||
# no flipping because `block_difficulty` in this context
|
|
||||||
# is a 32 bytes array
|
|
||||||
Hash256.fromEvmc c.host.getTxContext().block_difficulty
|
|
||||||
else:
|
|
||||||
c.vmState.random
|
|
||||||
|
|
||||||
template getGasLimit*(c: Computation): GasInt =
|
template getGasLimit*(c: Computation): GasInt =
|
||||||
when evmc_enabled:
|
when evmc_enabled:
|
||||||
c.host.getTxContext().block_gas_limit.GasInt
|
c.host.getTxContext().block_gas_limit.GasInt
|
||||||
|
|
|
@ -20,9 +20,6 @@ proc hostGetTxContextImpl(ctx: Computation): nimbus_tx_context {.cdecl.} =
|
||||||
# EIP-4399
|
# EIP-4399
|
||||||
# Transfer block randomness to difficulty OPCODE
|
# Transfer block randomness to difficulty OPCODE
|
||||||
let difficulty = toEvmc(vmstate.difficulty)
|
let difficulty = toEvmc(vmstate.difficulty)
|
||||||
if difficulty == default(evmc_bytes32): # or difficulty.isZero
|
|
||||||
result.block_difficulty = vmState.random.toEvmc
|
|
||||||
else:
|
|
||||||
result.block_difficulty = difficulty
|
result.block_difficulty = difficulty
|
||||||
|
|
||||||
result.chain_id = toEvmc(vmstate.chaindb.config.chainId.uint.u256)
|
result.chain_id = toEvmc(vmstate.chaindb.config.chainId.uint.u256)
|
||||||
|
|
|
@ -761,8 +761,7 @@ const
|
||||||
FkPetersburg: SpuriousGasFees,
|
FkPetersburg: SpuriousGasFees,
|
||||||
FkIstanbul: IstanbulGasFees,
|
FkIstanbul: IstanbulGasFees,
|
||||||
FkBerlin: BerlinGasFees,
|
FkBerlin: BerlinGasFees,
|
||||||
FkLondon: LondonGasFees,
|
FkLondon: LondonGasFees
|
||||||
FkPostMerge: LondonGasFees
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -774,7 +773,6 @@ gasCosts(FkConstantinople, constantinople, ConstantinopleGasCosts)
|
||||||
gasCosts(FkIstanbul, istanbul, IstanbulGasCosts)
|
gasCosts(FkIstanbul, istanbul, IstanbulGasCosts)
|
||||||
gasCosts(FkBerlin, berlin, BerlinGasCosts)
|
gasCosts(FkBerlin, berlin, BerlinGasCosts)
|
||||||
gasCosts(FkLondon, london, LondonGasCosts)
|
gasCosts(FkLondon, london, LondonGasCosts)
|
||||||
gasCosts(FkPostMerge, postMerge, PostMergeGasCosts)
|
|
||||||
|
|
||||||
proc forkToSchedule*(fork: Fork): GasCosts =
|
proc forkToSchedule*(fork: Fork): GasCosts =
|
||||||
if fork < FkHomestead:
|
if fork < FkHomestead:
|
||||||
|
@ -791,10 +789,8 @@ proc forkToSchedule*(fork: Fork): GasCosts =
|
||||||
IstanbulGasCosts
|
IstanbulGasCosts
|
||||||
elif fork < FkLondon:
|
elif fork < FkLondon:
|
||||||
BerlinGasCosts
|
BerlinGasCosts
|
||||||
elif fork < FkPostMerge:
|
|
||||||
LondonGasCosts
|
|
||||||
else:
|
else:
|
||||||
PostMergeGasCosts
|
LondonGasCosts
|
||||||
|
|
||||||
const
|
const
|
||||||
## Precompile costs
|
## Precompile costs
|
||||||
|
|
|
@ -412,11 +412,6 @@ op difficulty, inline = true:
|
||||||
## 0x44, Get the block's difficulty
|
## 0x44, Get the block's difficulty
|
||||||
push: c.getDifficulty()
|
push: c.getDifficulty()
|
||||||
|
|
||||||
op randomEIP4399, inline = true:
|
|
||||||
## since EIP-4399 0x44 renamed from `DIFFICULTY` to `RANDOM`
|
|
||||||
## 0x44, Get the block's randomness
|
|
||||||
push: c.getRandom()
|
|
||||||
|
|
||||||
op gasLimit, inline = true:
|
op gasLimit, inline = true:
|
||||||
## 0x45, Get the block's gas limit
|
## 0x45, Get the block's gas limit
|
||||||
push: c.getGasLimit()
|
push: c.getGasLimit()
|
||||||
|
|
|
@ -254,13 +254,6 @@ proc genLondonJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTi
|
||||||
|
|
||||||
let LondonOpDispatch {.compileTime.}: array[Op, NimNode] = genLondonJumpTable(BerlinOpDispatch)
|
let LondonOpDispatch {.compileTime.}: array[Op, NimNode] = genLondonJumpTable(BerlinOpDispatch)
|
||||||
|
|
||||||
proc genPostMergeJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} =
|
|
||||||
result = ops
|
|
||||||
# EIP-4399
|
|
||||||
result[Random] = newIdentNode "randomEIP4399"
|
|
||||||
|
|
||||||
let PostMergeOpDispatch {.compileTime.}: array[Op, NimNode] = genPostMergeJumpTable(LondonOpDispatch)
|
|
||||||
|
|
||||||
proc opTableToCaseStmt(opTable: array[Op, NimNode], c: NimNode): NimNode =
|
proc opTableToCaseStmt(opTable: array[Op, NimNode], c: NimNode): NimNode =
|
||||||
|
|
||||||
let instr = quote do: `c`.instr
|
let instr = quote do: `c`.instr
|
||||||
|
@ -352,9 +345,6 @@ macro genBerlinDispatch(c: Computation): untyped =
|
||||||
macro genLondonDispatch(c: Computation): untyped =
|
macro genLondonDispatch(c: Computation): untyped =
|
||||||
result = opTableToCaseStmt(LondonOpDispatch, c)
|
result = opTableToCaseStmt(LondonOpDispatch, c)
|
||||||
|
|
||||||
macro genPostMergeDispatch(c: Computation): untyped =
|
|
||||||
result = opTableToCaseStmt(PostMergeOpDispatch, c)
|
|
||||||
|
|
||||||
proc frontierVM(c: Computation) =
|
proc frontierVM(c: Computation) =
|
||||||
genFrontierDispatch(c)
|
genFrontierDispatch(c)
|
||||||
|
|
||||||
|
@ -385,9 +375,6 @@ proc berlinVM(c: Computation) {.gcsafe.} =
|
||||||
proc londonVM(c: Computation) {.gcsafe.} =
|
proc londonVM(c: Computation) {.gcsafe.} =
|
||||||
genLondonDispatch(c)
|
genLondonDispatch(c)
|
||||||
|
|
||||||
proc postMergeVM(c: Computation) {.gcsafe.} =
|
|
||||||
genPostMergeDispatch(c)
|
|
||||||
|
|
||||||
proc selectVM(c: Computation, fork: Fork) {.gcsafe.} =
|
proc selectVM(c: Computation, fork: Fork) {.gcsafe.} =
|
||||||
# TODO: Optimise getting fork and updating opCodeExec only when necessary
|
# TODO: Optimise getting fork and updating opCodeExec only when necessary
|
||||||
case fork
|
case fork
|
||||||
|
@ -409,10 +396,8 @@ proc selectVM(c: Computation, fork: Fork) {.gcsafe.} =
|
||||||
c.istanbulVM()
|
c.istanbulVM()
|
||||||
of FkBerlin:
|
of FkBerlin:
|
||||||
c.berlinVM()
|
c.berlinVM()
|
||||||
of FkLondon:
|
|
||||||
c.londonVM()
|
|
||||||
else:
|
else:
|
||||||
c.postMergeVM()
|
c.londonVM()
|
||||||
|
|
||||||
proc executeOpcodes(c: Computation) =
|
proc executeOpcodes(c: Computation) =
|
||||||
let fork = c.fork
|
let fork = c.fork
|
||||||
|
|
|
@ -62,6 +62,7 @@ proc init(
|
||||||
random: Hash256;
|
random: Hash256;
|
||||||
miner: EthAddress;
|
miner: EthAddress;
|
||||||
chainDB: BaseChainDB;
|
chainDB: BaseChainDB;
|
||||||
|
ttdReached: bool;
|
||||||
tracer: TransactionTracer)
|
tracer: TransactionTracer)
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
## Initialisation helper
|
## Initialisation helper
|
||||||
|
@ -73,6 +74,7 @@ proc init(
|
||||||
self.fee = fee
|
self.fee = fee
|
||||||
self.random = random
|
self.random = random
|
||||||
self.chaindb = chainDB
|
self.chaindb = chainDB
|
||||||
|
self.ttdReached = ttdReached
|
||||||
self.tracer = tracer
|
self.tracer = tracer
|
||||||
self.logEntries = @[]
|
self.logEntries = @[]
|
||||||
self.stateDB = ac
|
self.stateDB = ac
|
||||||
|
@ -89,6 +91,7 @@ proc init(
|
||||||
random: Hash256;
|
random: Hash256;
|
||||||
miner: EthAddress;
|
miner: EthAddress;
|
||||||
chainDB: BaseChainDB;
|
chainDB: BaseChainDB;
|
||||||
|
ttdReached: bool;
|
||||||
tracerFlags: set[TracerFlags])
|
tracerFlags: set[TracerFlags])
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
var tracer: TransactionTracer
|
var tracer: TransactionTracer
|
||||||
|
@ -102,6 +105,7 @@ proc init(
|
||||||
random = random,
|
random = random,
|
||||||
miner = miner,
|
miner = miner,
|
||||||
chainDB = chainDB,
|
chainDB = chainDB,
|
||||||
|
ttdReached= ttdReached,
|
||||||
tracer = tracer)
|
tracer = tracer)
|
||||||
|
|
||||||
# --------------
|
# --------------
|
||||||
|
@ -124,6 +128,7 @@ proc new*(
|
||||||
random: Hash256; ## tx env: POS block randomness
|
random: Hash256; ## tx env: POS block randomness
|
||||||
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
|
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
|
||||||
chainDB: BaseChainDB; ## block chain database
|
chainDB: BaseChainDB; ## block chain database
|
||||||
|
ttdReached: bool; ## total terminal difficulty reached
|
||||||
tracerFlags: set[TracerFlags] = {};
|
tracerFlags: set[TracerFlags] = {};
|
||||||
pruneTrie: bool = true): T
|
pruneTrie: bool = true): T
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
|
@ -144,6 +149,7 @@ proc new*(
|
||||||
random = random,
|
random = random,
|
||||||
miner = miner,
|
miner = miner,
|
||||||
chainDB = chainDB,
|
chainDB = chainDB,
|
||||||
|
ttdReached = ttdReached,
|
||||||
tracerFlags = tracerFlags)
|
tracerFlags = tracerFlags)
|
||||||
|
|
||||||
proc reinit*(self: BaseVMState; ## Object descriptor
|
proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
|
@ -153,6 +159,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
fee: Option[Uint256]; ## tx env: optional base fee
|
fee: Option[Uint256]; ## tx env: optional base fee
|
||||||
random: Hash256; ## tx env: POS block randomness
|
random: Hash256; ## tx env: POS block randomness
|
||||||
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
|
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
|
||||||
|
ttdReached:bool; ## total terminal difficulty reached
|
||||||
pruneTrie: bool = true): bool
|
pruneTrie: bool = true): bool
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
## Re-initialise state descriptor. The `AccountsCache` database is
|
## Re-initialise state descriptor. The `AccountsCache` database is
|
||||||
|
@ -179,10 +186,17 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
random = random,
|
random = random,
|
||||||
miner = miner,
|
miner = miner,
|
||||||
chainDB = db,
|
chainDB = db,
|
||||||
|
ttdReached = ttdReached,
|
||||||
tracer = tracer)
|
tracer = tracer)
|
||||||
return true
|
return true
|
||||||
# else: false
|
# else: false
|
||||||
|
|
||||||
|
proc ttd(chainDB: BaseChainDB): DifficultyInt =
|
||||||
|
if chainDB.config.terminalTotalDifficulty.isSome:
|
||||||
|
chainDB.config.terminalTotalDifficulty.get()
|
||||||
|
else:
|
||||||
|
high(DifficultyInt)
|
||||||
|
|
||||||
proc reinit*(self: BaseVMState; ## Object descriptor
|
proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
parent: BlockHeader; ## parent header, account sync pos.
|
parent: BlockHeader; ## parent header, account sync pos.
|
||||||
header: BlockHeader; ## header with tx environment data fields
|
header: BlockHeader; ## header with tx environment data fields
|
||||||
|
@ -194,6 +208,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
##
|
##
|
||||||
## It requires the `header` argument properly initalised so that for PoA
|
## It requires the `header` argument properly initalised so that for PoA
|
||||||
## networks, the miner address is retrievable via `ecRecover()`.
|
## networks, the miner address is retrievable via `ecRecover()`.
|
||||||
|
let ttdReached = self.chainDB.totalDifficulty + header.difficulty > self.chainDB.ttd
|
||||||
self.reinit(
|
self.reinit(
|
||||||
parent = parent,
|
parent = parent,
|
||||||
timestamp = header.timestamp,
|
timestamp = header.timestamp,
|
||||||
|
@ -201,6 +216,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
fee = header.fee,
|
fee = header.fee,
|
||||||
random = header.random,
|
random = header.random,
|
||||||
miner = self.chainDB.getMinerAddress(header),
|
miner = self.chainDB.getMinerAddress(header),
|
||||||
|
ttdReached= ttdReached,
|
||||||
pruneTrie = pruneTrie)
|
pruneTrie = pruneTrie)
|
||||||
|
|
||||||
proc reinit*(self: BaseVMState; ## Object descriptor
|
proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
|
@ -231,6 +247,7 @@ proc init*(
|
||||||
##
|
##
|
||||||
## It requires the `header` argument properly initalised so that for PoA
|
## It requires the `header` argument properly initalised so that for PoA
|
||||||
## networks, the miner address is retrievable via `ecRecover()`.
|
## networks, the miner address is retrievable via `ecRecover()`.
|
||||||
|
let ttdReached = chainDB.totalDifficulty + header.difficulty > chainDB.ttd
|
||||||
self.init(AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie),
|
self.init(AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie),
|
||||||
parent,
|
parent,
|
||||||
header.timestamp,
|
header.timestamp,
|
||||||
|
@ -239,6 +256,7 @@ proc init*(
|
||||||
header.random,
|
header.random,
|
||||||
chainDB.getMinerAddress(header),
|
chainDB.getMinerAddress(header),
|
||||||
chainDB,
|
chainDB,
|
||||||
|
ttdReached,
|
||||||
tracerFlags)
|
tracerFlags)
|
||||||
|
|
||||||
proc new*(
|
proc new*(
|
||||||
|
@ -308,9 +326,9 @@ method blockNumber*(vmState: BaseVMState): BlockNumber {.base, gcsafe.} =
|
||||||
vmState.parent.blockNumber + 1
|
vmState.parent.blockNumber + 1
|
||||||
|
|
||||||
method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
|
method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
|
||||||
if vmState.fork >= FkPostMerge:
|
if vmState.ttdReached:
|
||||||
# EIP-4399/EIP-3675
|
# EIP-4399/EIP-3675
|
||||||
0.u256
|
UInt256.fromBytesBE(vmState.random.data, allowPadding = false)
|
||||||
else:
|
else:
|
||||||
vmState.chainDB.config.calcDifficulty(vmState.timestamp, vmState.parent)
|
vmState.chainDB.config.calcDifficulty(vmState.timestamp, vmState.parent)
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ type
|
||||||
gasLimit* : GasInt
|
gasLimit* : GasInt
|
||||||
fee* : Option[Uint256]
|
fee* : Option[Uint256]
|
||||||
random* : Hash256
|
random* : Hash256
|
||||||
|
ttdReached* : bool
|
||||||
name* : string
|
name* : string
|
||||||
flags* : set[VMFlag]
|
flags* : set[VMFlag]
|
||||||
tracer* : TransactionTracer
|
tracer* : TransactionTracer
|
||||||
|
|
|
@ -58,9 +58,6 @@ template getBlockNumber*(c: Computation): Uint256 =
|
||||||
template getDifficulty*(c: Computation): DifficultyInt =
|
template getDifficulty*(c: Computation): DifficultyInt =
|
||||||
c.vmState.difficulty
|
c.vmState.difficulty
|
||||||
|
|
||||||
template getRandom*(c: Computation): Hash256 =
|
|
||||||
c.vmState.random
|
|
||||||
|
|
||||||
template getGasLimit*(c: Computation): GasInt =
|
template getGasLimit*(c: Computation): GasInt =
|
||||||
c.vmState.gasLimit
|
c.vmState.gasLimit
|
||||||
|
|
||||||
|
|
|
@ -730,11 +730,9 @@ const
|
||||||
FkPetersburg: SpuriousGasFees,
|
FkPetersburg: SpuriousGasFees,
|
||||||
FkIstanbul: IstanbulGasFees,
|
FkIstanbul: IstanbulGasFees,
|
||||||
FkBerlin: BerlinGasFees,
|
FkBerlin: BerlinGasFees,
|
||||||
FkLondon: LondonGasFees,
|
FkLondon: LondonGasFees
|
||||||
FkPostMerge: LondonGasFees
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
gasCosts(FkFrontier, base, BaseGasCosts)
|
gasCosts(FkFrontier, base, BaseGasCosts)
|
||||||
gasCosts(FkHomestead, homestead, HomesteadGasCosts)
|
gasCosts(FkHomestead, homestead, HomesteadGasCosts)
|
||||||
gasCosts(FkTangerine, tangerine, TangerineGasCosts)
|
gasCosts(FkTangerine, tangerine, TangerineGasCosts)
|
||||||
|
@ -743,7 +741,6 @@ gasCosts(FkConstantinople, constantinople, ConstantinopleGasCosts)
|
||||||
gasCosts(FkIstanbul, istanbul, IstanbulGasCosts)
|
gasCosts(FkIstanbul, istanbul, IstanbulGasCosts)
|
||||||
gasCosts(FkBerlin, berlin, BerlinGasCosts)
|
gasCosts(FkBerlin, berlin, BerlinGasCosts)
|
||||||
gasCosts(FkLondon, london, LondonGasCosts)
|
gasCosts(FkLondon, london, LondonGasCosts)
|
||||||
gasCosts(FkPostMerge, postMerge, PostMergeGasCosts)
|
|
||||||
|
|
||||||
proc forkToSchedule*(fork: Fork): GasCosts =
|
proc forkToSchedule*(fork: Fork): GasCosts =
|
||||||
if fork < FkHomestead:
|
if fork < FkHomestead:
|
||||||
|
@ -760,10 +757,8 @@ proc forkToSchedule*(fork: Fork): GasCosts =
|
||||||
IstanbulGasCosts
|
IstanbulGasCosts
|
||||||
elif fork < FkLondon:
|
elif fork < FkLondon:
|
||||||
BerlinGasCosts
|
BerlinGasCosts
|
||||||
elif fork < FkPostMerge:
|
|
||||||
LondonGasCosts
|
|
||||||
else:
|
else:
|
||||||
PostMergeGasCosts
|
LondonGasCosts
|
||||||
|
|
||||||
const
|
const
|
||||||
## Precompile costs
|
## Precompile costs
|
||||||
|
|
|
@ -53,11 +53,6 @@ const
|
||||||
k.cpt.stack.push:
|
k.cpt.stack.push:
|
||||||
k.cpt.getDifficulty
|
k.cpt.getDifficulty
|
||||||
|
|
||||||
randomOp: Vm2OpFn = proc (k: var Vm2Ctx) =
|
|
||||||
## 0x44, Get the block's randomness
|
|
||||||
k.cpt.stack.push:
|
|
||||||
k.cpt.getRandom
|
|
||||||
|
|
||||||
gasLimitOp: Vm2OpFn = proc (k: var Vm2Ctx) =
|
gasLimitOp: Vm2OpFn = proc (k: var Vm2Ctx) =
|
||||||
## 0x45, Get the block's gas limit
|
## 0x45, Get the block's gas limit
|
||||||
k.cpt.stack.push:
|
k.cpt.stack.push:
|
||||||
|
@ -118,7 +113,7 @@ const
|
||||||
post: vm2OpIgnore)),
|
post: vm2OpIgnore)),
|
||||||
|
|
||||||
(opCode: Difficulty, ## 0x44, Block difficulty
|
(opCode: Difficulty, ## 0x44, Block difficulty
|
||||||
forks: Vm2OpAllForks - Vm2OpPostMergeAndLater,
|
forks: Vm2OpAllForks,
|
||||||
name: "difficulty",
|
name: "difficulty",
|
||||||
info: "Get the block's difficulty",
|
info: "Get the block's difficulty",
|
||||||
exec: (prep: vm2OpIgnore,
|
exec: (prep: vm2OpIgnore,
|
||||||
|
@ -155,14 +150,6 @@ const
|
||||||
info: "Get current block's EIP-1559 base fee",
|
info: "Get current block's EIP-1559 base fee",
|
||||||
exec: (prep: vm2OpIgnore,
|
exec: (prep: vm2OpIgnore,
|
||||||
run: baseFeeOp,
|
run: baseFeeOp,
|
||||||
post: vm2OpIgnore)),
|
|
||||||
|
|
||||||
(opCode: Random, ## 0x44, EIP-4399 Block randomness.
|
|
||||||
forks: Vm2OpPostMergeAndLater,
|
|
||||||
name: "random",
|
|
||||||
info: "Get current block's EIP-4399 randomness",
|
|
||||||
exec: (prep: vm2OpIgnore,
|
|
||||||
run: randomOp,
|
|
||||||
post: vm2OpIgnore))]
|
post: vm2OpIgnore))]
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -81,9 +81,6 @@ const
|
||||||
Vm2OpLondonAndLater* =
|
Vm2OpLondonAndLater* =
|
||||||
Vm2OpBerlinAndLater - {FkBerlin}
|
Vm2OpBerlinAndLater - {FkBerlin}
|
||||||
|
|
||||||
Vm2OpPostMergeAndLater* =
|
|
||||||
Vm2OpLondonAndLater - {FkLondon}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -61,6 +61,7 @@ proc init(
|
||||||
random: Hash256;
|
random: Hash256;
|
||||||
miner: EthAddress;
|
miner: EthAddress;
|
||||||
chainDB: BaseChainDB;
|
chainDB: BaseChainDB;
|
||||||
|
ttdReached: bool;
|
||||||
tracer: TransactionTracer)
|
tracer: TransactionTracer)
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
## Initialisation helper
|
## Initialisation helper
|
||||||
|
@ -72,6 +73,7 @@ proc init(
|
||||||
self.fee = fee
|
self.fee = fee
|
||||||
self.random = random
|
self.random = random
|
||||||
self.chaindb = chainDB
|
self.chaindb = chainDB
|
||||||
|
self.ttdReached = ttdReached
|
||||||
self.tracer = tracer
|
self.tracer = tracer
|
||||||
self.logEntries = @[]
|
self.logEntries = @[]
|
||||||
self.stateDB = ac
|
self.stateDB = ac
|
||||||
|
@ -88,6 +90,7 @@ proc init(
|
||||||
random: Hash256;
|
random: Hash256;
|
||||||
miner: EthAddress;
|
miner: EthAddress;
|
||||||
chainDB: BaseChainDB;
|
chainDB: BaseChainDB;
|
||||||
|
ttdReached: bool;
|
||||||
tracerFlags: set[TracerFlags])
|
tracerFlags: set[TracerFlags])
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
var tracer: TransactionTracer
|
var tracer: TransactionTracer
|
||||||
|
@ -101,6 +104,7 @@ proc init(
|
||||||
random = random,
|
random = random,
|
||||||
miner = miner,
|
miner = miner,
|
||||||
chainDB = chainDB,
|
chainDB = chainDB,
|
||||||
|
ttdReached= ttdReached,
|
||||||
tracer = tracer)
|
tracer = tracer)
|
||||||
|
|
||||||
# --------------
|
# --------------
|
||||||
|
@ -123,6 +127,7 @@ proc new*(
|
||||||
random: Hash256; ## tx env: POS block randomness
|
random: Hash256; ## tx env: POS block randomness
|
||||||
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
|
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
|
||||||
chainDB: BaseChainDB; ## block chain database
|
chainDB: BaseChainDB; ## block chain database
|
||||||
|
ttdReached: bool; ## total terminal difficulty reached
|
||||||
tracerFlags: set[TracerFlags] = {};
|
tracerFlags: set[TracerFlags] = {};
|
||||||
pruneTrie: bool = true): T
|
pruneTrie: bool = true): T
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
|
@ -143,6 +148,7 @@ proc new*(
|
||||||
random = random,
|
random = random,
|
||||||
miner = miner,
|
miner = miner,
|
||||||
chainDB = chainDB,
|
chainDB = chainDB,
|
||||||
|
ttdReached = ttdReached,
|
||||||
tracerFlags = tracerFlags)
|
tracerFlags = tracerFlags)
|
||||||
|
|
||||||
proc reinit*(self: BaseVMState; ## Object descriptor
|
proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
|
@ -152,6 +158,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
fee: Option[Uint256]; ## tx env: optional base fee
|
fee: Option[Uint256]; ## tx env: optional base fee
|
||||||
random: Hash256; ## tx env: POS block randomness
|
random: Hash256; ## tx env: POS block randomness
|
||||||
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
|
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
|
||||||
|
ttdReached:bool; ## total terminal difficulty reached
|
||||||
pruneTrie: bool = true): bool
|
pruneTrie: bool = true): bool
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
## Re-initialise state descriptor. The `AccountsCache` database is
|
## Re-initialise state descriptor. The `AccountsCache` database is
|
||||||
|
@ -178,10 +185,17 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
random = random,
|
random = random,
|
||||||
miner = miner,
|
miner = miner,
|
||||||
chainDB = db,
|
chainDB = db,
|
||||||
|
ttdReached = ttdReached,
|
||||||
tracer = tracer)
|
tracer = tracer)
|
||||||
return true
|
return true
|
||||||
# else: false
|
# else: false
|
||||||
|
|
||||||
|
proc ttd(chainDB: BaseChainDB): DifficultyInt =
|
||||||
|
if chainDB.config.terminalTotalDifficulty.isSome:
|
||||||
|
chainDB.config.terminalTotalDifficulty.get()
|
||||||
|
else:
|
||||||
|
high(DifficultyInt)
|
||||||
|
|
||||||
proc reinit*(self: BaseVMState; ## Object descriptor
|
proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
parent: BlockHeader; ## parent header, account sync pos.
|
parent: BlockHeader; ## parent header, account sync pos.
|
||||||
header: BlockHeader; ## header with tx environment data fields
|
header: BlockHeader; ## header with tx environment data fields
|
||||||
|
@ -193,6 +207,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
##
|
##
|
||||||
## It requires the `header` argument properly initalised so that for PoA
|
## It requires the `header` argument properly initalised so that for PoA
|
||||||
## networks, the miner address is retrievable via `ecRecover()`.
|
## networks, the miner address is retrievable via `ecRecover()`.
|
||||||
|
let ttdReached = self.chainDB.totalDifficulty + header.difficulty > self.chainDB.ttd
|
||||||
self.reinit(
|
self.reinit(
|
||||||
parent = parent,
|
parent = parent,
|
||||||
timestamp = header.timestamp,
|
timestamp = header.timestamp,
|
||||||
|
@ -200,6 +215,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
fee = header.fee,
|
fee = header.fee,
|
||||||
random = header.random,
|
random = header.random,
|
||||||
miner = self.chainDB.getMinerAddress(header),
|
miner = self.chainDB.getMinerAddress(header),
|
||||||
|
ttdReached= ttdReached,
|
||||||
pruneTrie = pruneTrie)
|
pruneTrie = pruneTrie)
|
||||||
|
|
||||||
proc reinit*(self: BaseVMState; ## Object descriptor
|
proc reinit*(self: BaseVMState; ## Object descriptor
|
||||||
|
@ -230,6 +246,7 @@ proc init*(
|
||||||
##
|
##
|
||||||
## It requires the `header` argument properly initalised so that for PoA
|
## It requires the `header` argument properly initalised so that for PoA
|
||||||
## networks, the miner address is retrievable via `ecRecover()`.
|
## networks, the miner address is retrievable via `ecRecover()`.
|
||||||
|
let ttdReached = chainDB.totalDifficulty + header.difficulty > chainDB.ttd
|
||||||
self.init(AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie),
|
self.init(AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie),
|
||||||
parent,
|
parent,
|
||||||
header.timestamp,
|
header.timestamp,
|
||||||
|
@ -238,6 +255,7 @@ proc init*(
|
||||||
header.random,
|
header.random,
|
||||||
chainDB.getMinerAddress(header),
|
chainDB.getMinerAddress(header),
|
||||||
chainDB,
|
chainDB,
|
||||||
|
ttdReached,
|
||||||
tracerFlags)
|
tracerFlags)
|
||||||
|
|
||||||
proc new*(
|
proc new*(
|
||||||
|
@ -295,9 +313,9 @@ method blockNumber*(vmState: BaseVMState): BlockNumber {.base, gcsafe.} =
|
||||||
vmState.parent.blockNumber + 1
|
vmState.parent.blockNumber + 1
|
||||||
|
|
||||||
method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
|
method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
|
||||||
if vmState.fork >= FkPostMerge:
|
if vmState.ttdReached:
|
||||||
# EIP-4399/EIP-3675
|
# EIP-4399/EIP-3675
|
||||||
0.u256
|
UInt256.fromBytesBE(vmState.random.data, allowPadding = false)
|
||||||
else:
|
else:
|
||||||
vmState.chainDB.config.calcDifficulty(vmState.timestamp, vmState.parent)
|
vmState.chainDB.config.calcDifficulty(vmState.timestamp, vmState.parent)
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ type
|
||||||
gasLimit* : GasInt
|
gasLimit* : GasInt
|
||||||
fee* : Option[Uint256]
|
fee* : Option[Uint256]
|
||||||
random* : Hash256
|
random* : Hash256
|
||||||
|
ttdReached* : bool
|
||||||
name* : string
|
name* : string
|
||||||
flags* : set[VMFlag]
|
flags* : set[VMFlag]
|
||||||
tracer* : TransactionTracer
|
tracer* : TransactionTracer
|
||||||
|
|
|
@ -324,9 +324,7 @@ proc opEnvMain*() =
|
||||||
fork: berlin
|
fork: berlin
|
||||||
gasused: 2603
|
gasused: 2603
|
||||||
|
|
||||||
when not defined(evmc_enabled):
|
vmState.ttdReached = true
|
||||||
# TODO: enable this test for EVMC when EVMC
|
|
||||||
# support this EVM version
|
|
||||||
assembler:
|
assembler:
|
||||||
title: "EIP-4399 RANDOM 0"
|
title: "EIP-4399 RANDOM 0"
|
||||||
code:
|
code:
|
||||||
|
@ -334,7 +332,7 @@ proc opEnvMain*() =
|
||||||
STOP
|
STOP
|
||||||
stack:
|
stack:
|
||||||
"0x0000000000000000000000000000000000000000000000000000000000000000"
|
"0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
fork: postmerge
|
fork: london
|
||||||
|
|
||||||
vmState.random = EMPTY_UNCLE_HASH
|
vmState.random = EMPTY_UNCLE_HASH
|
||||||
assembler:
|
assembler:
|
||||||
|
@ -344,7 +342,9 @@ proc opEnvMain*() =
|
||||||
STOP
|
STOP
|
||||||
stack:
|
stack:
|
||||||
"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||||
fork: postmerge
|
fork: london
|
||||||
|
|
||||||
|
vmState.ttdReached = false
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
opEnvMain()
|
opEnvMain()
|
||||||
|
|
Loading…
Reference in New Issue