2022-01-18 14:40:02 +00:00
|
|
|
# Nimbus
|
2024-02-16 09:08:07 +00:00
|
|
|
# Copyright (c) 2022-2024 Status Research & Development GmbH
|
2022-01-18 14:40:02 +00:00
|
|
|
# Licensed under either of
|
|
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
|
|
|
# http://opensource.org/licenses/MIT)
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except
|
|
|
|
# according to those terms.
|
|
|
|
|
2024-06-07 21:39:58 +00:00
|
|
|
{.push raises: [].}
|
|
|
|
|
2022-01-18 14:40:02 +00:00
|
|
|
## Transaction Pool Block Chain Packer Environment
|
|
|
|
## ===============================================
|
|
|
|
##
|
|
|
|
|
|
|
|
import
|
2024-06-07 21:39:58 +00:00
|
|
|
results,
|
2022-12-02 04:35:41 +00:00
|
|
|
../../common/common,
|
2022-01-18 14:40:02 +00:00
|
|
|
../../constants,
|
2023-12-12 19:12:56 +00:00
|
|
|
../../db/ledger,
|
2022-12-02 04:35:41 +00:00
|
|
|
../../utils/utils,
|
2024-06-17 07:56:39 +00:00
|
|
|
../../evm/state,
|
|
|
|
../../evm/types,
|
2024-07-19 09:24:36 +00:00
|
|
|
../pow/header,
|
2024-04-24 00:50:50 +00:00
|
|
|
../eip4844,
|
2022-12-06 05:55:40 +00:00
|
|
|
../casper,
|
2024-07-19 09:24:36 +00:00
|
|
|
eth/eip1559
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
TxChainRef* = ref object ##\
|
|
|
|
## State cache of the transaction environment for creating a new\
|
|
|
|
## block. This state is typically synchrionised with the canonical\
|
|
|
|
## block chain head when updated.
|
2022-12-02 04:35:41 +00:00
|
|
|
com: CommonRef ## Block chain config
|
2022-01-18 14:40:02 +00:00
|
|
|
roAcc: ReadOnlyStateDB ## Accounts cache fixed on current sync header
|
2022-12-06 05:55:40 +00:00
|
|
|
prepHeader: BlockHeader ## Prepared Header from Consensus Engine
|
2022-06-14 06:01:51 +00:00
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
vmState: BaseVMState ## current tx/packer environment
|
|
|
|
receiptsRoot: Hash256
|
|
|
|
logsBloom: BloomFilter
|
|
|
|
txRoot: Hash256 ## `rootHash` after packing
|
|
|
|
stateRoot: Hash256 ## `stateRoot` after packing
|
|
|
|
|
2022-01-18 14:40:02 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Private functions
|
|
|
|
# ------------------------------------------------------------------------------
|
2024-07-19 09:24:36 +00:00
|
|
|
proc baseFeeGet(com: CommonRef; parent: BlockHeader): Opt[UInt256] =
|
|
|
|
## Calculates the `baseFee` of the head assuming this is the parent of a
|
|
|
|
## new block header to generate.
|
|
|
|
|
|
|
|
# Note that the baseFee is calculated for the next header
|
|
|
|
if not com.isLondonOrLater(parent.number+1):
|
|
|
|
return Opt.none(UInt256)
|
|
|
|
|
|
|
|
# If the new block is the first EIP-1559 block, return initial base fee.
|
|
|
|
if not com.isLondonOrLater(parent.number):
|
|
|
|
return Opt.some(EIP1559_INITIAL_BASE_FEE)
|
|
|
|
|
|
|
|
Opt.some calcEip1599BaseFee(
|
|
|
|
parent.gasLimit,
|
|
|
|
parent.gasUsed,
|
|
|
|
parent.baseFeePerGas.get(0.u256))
|
|
|
|
|
|
|
|
proc gasLimitsGet(com: CommonRef; parent: BlockHeader): GasInt =
|
|
|
|
if com.isLondonOrLater(parent.number+1):
|
|
|
|
var parentGasLimit = parent.gasLimit
|
|
|
|
if not com.isLondonOrLater(parent.number):
|
|
|
|
# Bump by 2x
|
|
|
|
parentGasLimit = parent.gasLimit * EIP1559_ELASTICITY_MULTIPLIER
|
|
|
|
calcGasLimit1559(parentGasLimit, desiredLimit = DEFAULT_GAS_LIMIT)
|
|
|
|
else:
|
|
|
|
computeGasLimit(
|
|
|
|
parent.gasUsed,
|
|
|
|
parent.gasLimit,
|
|
|
|
gasFloor = DEFAULT_GAS_LIMIT,
|
|
|
|
gasCeil = DEFAULT_GAS_LIMIT)
|
|
|
|
|
|
|
|
func prepareHeader(dh: TxChainRef) =
|
2024-05-28 18:26:51 +00:00
|
|
|
dh.com.pos.prepare(dh.prepHeader)
|
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
func prepareForSeal(dh: TxChainRef; header: var BlockHeader) =
|
2024-05-28 18:26:51 +00:00
|
|
|
dh.com.pos.prepareForSeal(header)
|
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
func getTimestamp(dh: TxChainRef): EthTime =
|
2024-05-28 18:26:51 +00:00
|
|
|
dh.com.pos.timestamp
|
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
func feeRecipient*(dh: TxChainRef): EthAddress =
|
|
|
|
## Getter
|
|
|
|
dh.com.pos.feeRecipient
|
2022-01-18 14:40:02 +00:00
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
proc resetTxEnv(dh: TxChainRef; parent: BlockHeader) =
|
2022-12-05 11:25:44 +00:00
|
|
|
# do hardfork transition before
|
|
|
|
# BaseVMState querying any hardfork/consensus from CommonRef
|
2023-05-23 05:25:42 +00:00
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
let timestamp = dh.getTimestamp()
|
2024-06-07 21:39:58 +00:00
|
|
|
dh.com.hardForkTransition(
|
2024-06-14 07:31:08 +00:00
|
|
|
parent.blockHash, parent.number+1, Opt.some(timestamp))
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.prepareHeader()
|
2022-12-05 11:25:44 +00:00
|
|
|
|
2022-06-14 06:01:51 +00:00
|
|
|
# we don't consider PoS difficulty here
|
|
|
|
# because that is handled in vmState
|
2023-09-24 15:25:41 +00:00
|
|
|
let blockCtx = BlockContext(
|
2024-04-24 00:50:50 +00:00
|
|
|
timestamp : dh.prepHeader.timestamp,
|
2024-07-19 09:24:36 +00:00
|
|
|
gasLimit : gasLimitsGet(dh.com, parent),
|
|
|
|
baseFeePerGas: baseFeeGet(dh.com, parent),
|
2024-04-24 00:50:50 +00:00
|
|
|
prevRandao : dh.prepHeader.prevRandao,
|
|
|
|
difficulty : dh.prepHeader.difficulty,
|
|
|
|
coinbase : dh.feeRecipient,
|
|
|
|
excessBlobGas: calcExcessBlobGas(parent),
|
2023-09-24 15:25:41 +00:00
|
|
|
)
|
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.vmState = BaseVMState.new(
|
2023-09-24 15:25:41 +00:00
|
|
|
parent = parent,
|
|
|
|
blockCtx = blockCtx,
|
|
|
|
com = dh.com)
|
2022-01-18 14:40:02 +00:00
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.txRoot = EMPTY_ROOT_HASH
|
|
|
|
dh.stateRoot = dh.vmState.parent.stateRoot
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
proc update(dh: TxChainRef; parent: BlockHeader)
|
2024-05-28 18:26:51 +00:00
|
|
|
{.gcsafe,raises: [].} =
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
let
|
2022-12-02 04:35:41 +00:00
|
|
|
db = dh.com.db
|
2024-05-29 11:06:49 +00:00
|
|
|
acc = LedgerRef.init(db, parent.stateRoot)
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
# Keep a separate accounts descriptor positioned at the sync point
|
|
|
|
dh.roAcc = ReadOnlyStateDB(acc)
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.resetTxEnv(parent)
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions, constructor
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2024-05-28 18:26:51 +00:00
|
|
|
proc new*(T: type TxChainRef; com: CommonRef): T
|
|
|
|
{.gcsafe, raises: [EVMError].} =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Constructor
|
|
|
|
new result
|
|
|
|
|
2022-12-02 04:35:41 +00:00
|
|
|
result.com = com
|
|
|
|
result.update(com.db.getCanonicalHead)
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2023-01-30 22:10:23 +00:00
|
|
|
proc getBalance*(dh: TxChainRef; account: EthAddress): UInt256 =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Wrapper around `vmState.readOnlyStateDB.getBalance()` for a `vmState`
|
|
|
|
## descriptor positioned at the `dh.head`. This might differ from the
|
|
|
|
## `dh.vmState.readOnlyStateDB.getBalance()` which returnes the current
|
|
|
|
## balance relative to what has been accumulated by the current packing
|
|
|
|
## procedure.
|
|
|
|
dh.roAcc.getBalance(account)
|
|
|
|
|
2023-01-30 22:10:23 +00:00
|
|
|
proc getNonce*(dh: TxChainRef; account: EthAddress): AccountNonce =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Wrapper around `vmState.readOnlyStateDB.getNonce()` for a `vmState`
|
|
|
|
## descriptor positioned at the `dh.head`. This might differ from the
|
|
|
|
## `dh.vmState.readOnlyStateDB.getNonce()` which returnes the current balance
|
|
|
|
## relative to what has been accumulated by the current packing procedure.
|
|
|
|
dh.roAcc.getNonce(account)
|
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
func baseFee*(dh: TxChainRef): GasInt =
|
|
|
|
## Getter, baseFee for the next bock header. This value is auto-generated
|
|
|
|
## when a new insertion point is set via `head=`.
|
|
|
|
if dh.vmState.blockCtx.baseFeePerGas.isSome:
|
|
|
|
dh.vmState.blockCtx.baseFeePerGas.get.truncate(GasInt)
|
|
|
|
else:
|
|
|
|
0.GasInt
|
|
|
|
|
|
|
|
func excessBlobGas*(dh: TxChainRef): uint64 =
|
|
|
|
## Getter, baseFee for the next bock header. This value is auto-generated
|
|
|
|
## when a new insertion point is set via `head=`.
|
|
|
|
dh.vmState.blockCtx.excessBlobGas
|
|
|
|
|
|
|
|
func blobGasUsed*(dh: TxChainRef): uint64 =
|
|
|
|
dh.vmState.blobGasUsed
|
|
|
|
|
|
|
|
func gasLimit*(dh: TxChainRef): GasInt =
|
|
|
|
dh.vmState.blockCtx.gasLimit
|
|
|
|
|
2022-01-18 14:40:02 +00:00
|
|
|
proc getHeader*(dh: TxChainRef): BlockHeader
|
2024-02-16 09:08:07 +00:00
|
|
|
{.gcsafe,raises: [].} =
|
2022-12-09 08:17:33 +00:00
|
|
|
## Generate a new header, a child of the cached `head`
|
2022-12-06 05:55:40 +00:00
|
|
|
result = BlockHeader(
|
2024-07-19 09:24:36 +00:00
|
|
|
parentHash: dh.vmState.parent.blockHash,
|
2024-06-14 07:31:08 +00:00
|
|
|
ommersHash: EMPTY_UNCLE_HASH,
|
|
|
|
coinbase: dh.prepHeader.coinbase,
|
2024-07-19 09:24:36 +00:00
|
|
|
stateRoot: dh.stateRoot,
|
|
|
|
txRoot: dh.txRoot,
|
|
|
|
receiptsRoot: dh.receiptsRoot,
|
|
|
|
logsBloom: dh.logsBloom,
|
2024-06-14 07:31:08 +00:00
|
|
|
difficulty: dh.prepHeader.difficulty,
|
2024-07-19 09:24:36 +00:00
|
|
|
number: dh.vmState.blockNumber,
|
|
|
|
gasLimit: dh.gasLimit,
|
|
|
|
gasUsed: dh.vmState.cumulativeGasUsed,
|
2024-06-14 07:31:08 +00:00
|
|
|
timestamp: dh.prepHeader.timestamp,
|
|
|
|
# extraData: Blob # signing data
|
|
|
|
# mixHash: Hash256 # mining hash for given difficulty
|
|
|
|
# nonce: BlockNonce # mining free vaiable
|
2024-07-19 09:24:36 +00:00
|
|
|
baseFeePerGas: dh.vmState.blockCtx.baseFeePerGas,
|
|
|
|
)
|
2022-01-18 14:40:02 +00:00
|
|
|
|
2024-07-17 10:05:53 +00:00
|
|
|
if dh.com.isShanghaiOrLater(result.timestamp):
|
2024-06-14 07:31:08 +00:00
|
|
|
result.withdrawalsRoot = Opt.some(calcWithdrawalsRoot(dh.com.pos.withdrawals))
|
2023-05-22 10:55:19 +00:00
|
|
|
|
2024-07-17 10:05:53 +00:00
|
|
|
if dh.com.isCancunOrLater(result.timestamp):
|
2024-06-14 07:31:08 +00:00
|
|
|
result.parentBeaconBlockRoot = Opt.some(dh.com.pos.parentBeaconBlockRoot)
|
2024-07-19 09:24:36 +00:00
|
|
|
result.blobGasUsed = Opt.some dh.blobGasUsed
|
|
|
|
result.excessBlobGas = Opt.some dh.excessBlobGas
|
2023-08-30 16:29:48 +00:00
|
|
|
|
2022-12-06 05:55:40 +00:00
|
|
|
dh.prepareForSeal(result)
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
proc clearAccounts*(dh: TxChainRef)
|
2024-05-28 18:26:51 +00:00
|
|
|
{.gcsafe,raises: [].} =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Reset transaction environment, e.g. before packing a new block
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.resetTxEnv(dh.vmState.parent)
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions, getters
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2024-05-28 18:26:51 +00:00
|
|
|
func com*(dh: TxChainRef): CommonRef =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Getter
|
2022-12-02 04:35:41 +00:00
|
|
|
dh.com
|
2022-01-18 14:40:02 +00:00
|
|
|
|
2024-05-28 18:26:51 +00:00
|
|
|
func head*(dh: TxChainRef): BlockHeader =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Getter
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.vmState.parent
|
2023-08-21 02:10:18 +00:00
|
|
|
|
2024-05-28 18:26:51 +00:00
|
|
|
func nextFork*(dh: TxChainRef): EVMFork =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Getter, fork of next block
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.vmState.fork
|
2022-01-18 14:40:02 +00:00
|
|
|
|
2024-05-28 18:26:51 +00:00
|
|
|
func vmState*(dh: TxChainRef): BaseVMState =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Getter, `BaseVmState` descriptor based on the current insertion point.
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.vmState
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions, setters
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
proc `head=`*(dh: TxChainRef; val: BlockHeader)
|
2024-05-28 18:26:51 +00:00
|
|
|
{.gcsafe,raises: [].} =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Setter, updates descriptor. This setter re-positions the `vmState` and
|
|
|
|
## account caches to a new insertion point on the block chain database.
|
|
|
|
dh.update(val)
|
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
func `receiptsRoot=`*(dh: TxChainRef; val: Hash256) =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Setter, implies `gasUsed`
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.receiptsRoot = val
|
2022-01-18 14:40:02 +00:00
|
|
|
|
2024-07-19 09:24:36 +00:00
|
|
|
func `logsBloom=`*(dh: TxChainRef; val: BloomFilter) =
|
|
|
|
## Setter, implies `gasUsed`
|
|
|
|
dh.logsBloom = val
|
2022-01-18 14:40:02 +00:00
|
|
|
|
2024-05-28 18:26:51 +00:00
|
|
|
func `stateRoot=`*(dh: TxChainRef; val: Hash256) =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Setter
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.stateRoot = val
|
2022-01-18 14:40:02 +00:00
|
|
|
|
2024-05-28 18:26:51 +00:00
|
|
|
func `txRoot=`*(dh: TxChainRef; val: Hash256) =
|
2022-01-18 14:40:02 +00:00
|
|
|
## Setter
|
2024-07-19 09:24:36 +00:00
|
|
|
dh.txRoot = val
|
2023-06-24 13:56:44 +00:00
|
|
|
|
2022-01-18 14:40:02 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# End
|
|
|
|
# ------------------------------------------------------------------------------
|