2023-11-01 03:32:09 +00:00
|
|
|
# Nimbus
|
2024-02-21 16:04:59 +00:00
|
|
|
# Copyright (c) 2022-2024 Status Research & Development GmbH
|
2023-11-01 03:32:09 +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.
|
|
|
|
|
2022-03-30 04:50:35 +00:00
|
|
|
import
|
2024-05-30 20:30:40 +00:00
|
|
|
std/tables,
|
2023-03-22 11:18:37 +00:00
|
|
|
eth/[keys],
|
2024-05-30 12:54:03 +00:00
|
|
|
stew/byteutils, results, unittest2,
|
2024-05-30 10:11:41 +00:00
|
|
|
../nimbus/db/ledger,
|
2022-12-02 04:39:12 +00:00
|
|
|
../nimbus/core/chain,
|
|
|
|
../nimbus/[config, transaction, constants],
|
|
|
|
../nimbus/core/tx_pool,
|
2022-12-06 05:55:40 +00:00
|
|
|
../nimbus/core/casper,
|
2022-12-02 04:39:12 +00:00
|
|
|
../nimbus/common/common,
|
2023-10-04 03:47:18 +00:00
|
|
|
../nimbus/utils/utils,
|
2024-05-30 20:30:40 +00:00
|
|
|
../nimbus/vm_types,
|
2022-03-30 04:50:35 +00:00
|
|
|
./test_txpool/helpers,
|
|
|
|
./macro_assembler
|
|
|
|
|
|
|
|
const
|
2022-04-04 08:34:59 +00:00
|
|
|
baseDir = [".", "tests"]
|
|
|
|
repoDir = [".", "customgenesis"]
|
|
|
|
genesisFile = "merge.json"
|
2022-03-30 04:50:35 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
TestEnv = object
|
|
|
|
nonce : uint64
|
|
|
|
chainId : ChainId
|
|
|
|
vaultKey: PrivateKey
|
|
|
|
conf : NimbusConf
|
2022-12-02 04:39:12 +00:00
|
|
|
com : CommonRef
|
|
|
|
chain : ChainRef
|
2022-03-30 04:50:35 +00:00
|
|
|
xp : TxPoolRef
|
|
|
|
|
|
|
|
const
|
|
|
|
signerKeyHex = "9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"
|
|
|
|
vaultKeyHex = "63b508a03c3b5937ceb903af8b1b0c191012ef6eb7e9c3fb7afa94e5d214d376"
|
|
|
|
recipient = hexToByteArray[20]("0000000000000000000000000000000000000318")
|
2022-04-04 02:01:39 +00:00
|
|
|
feeRecipient = hexToByteArray[20]("0000000000000000000000000000000000000212")
|
2022-03-30 04:50:35 +00:00
|
|
|
contractCode = evmByteCode:
|
|
|
|
PrevRandao # VAL
|
|
|
|
Push1 "0x11" # KEY
|
|
|
|
Sstore # OP
|
|
|
|
Stop
|
|
|
|
|
|
|
|
proc privKey(keyHex: string): PrivateKey =
|
|
|
|
let kRes = PrivateKey.fromHex(keyHex)
|
|
|
|
if kRes.isErr:
|
|
|
|
echo kRes.error
|
|
|
|
quit(QuitFailure)
|
|
|
|
|
|
|
|
kRes.get()
|
|
|
|
|
2024-05-30 20:30:40 +00:00
|
|
|
func makeTx(
|
|
|
|
t: var TestEnv, recipient: EthAddress, amount: UInt256,
|
|
|
|
payload: openArray[byte] = []): Transaction =
|
2022-03-30 04:50:35 +00:00
|
|
|
const
|
|
|
|
gasLimit = 75000.GasInt
|
|
|
|
gasPrice = 30.gwei
|
|
|
|
|
|
|
|
let tx = Transaction(
|
|
|
|
txType : TxLegacy,
|
|
|
|
chainId : t.chainId,
|
|
|
|
nonce : AccountNonce(t.nonce),
|
|
|
|
gasPrice: gasPrice,
|
|
|
|
gasLimit: gasLimit,
|
|
|
|
to : some(recipient),
|
|
|
|
value : amount,
|
|
|
|
payload : @payload
|
|
|
|
)
|
|
|
|
|
|
|
|
inc t.nonce
|
|
|
|
signTransaction(tx, t.vaultKey, t.chainId, eip155 = true)
|
|
|
|
|
2024-05-30 20:30:40 +00:00
|
|
|
func signTxWithNonce(
|
|
|
|
t: TestEnv, tx: Transaction, nonce: AccountNonce): Transaction =
|
2023-08-04 03:59:12 +00:00
|
|
|
var tx = tx
|
|
|
|
tx.nonce = nonce
|
|
|
|
signTransaction(tx, t.vaultKey, t.chainId, eip155 = true)
|
|
|
|
|
2023-07-25 05:28:17 +00:00
|
|
|
proc initEnv(envFork: HardFork): TestEnv =
|
2022-03-30 04:50:35 +00:00
|
|
|
var
|
|
|
|
conf = makeConfig(@[
|
2022-04-04 08:34:59 +00:00
|
|
|
"--custom-network:" & genesisFile.findFilePath(baseDir,repoDir).value
|
2022-03-30 04:50:35 +00:00
|
|
|
])
|
|
|
|
|
|
|
|
conf.networkParams.genesis.alloc[recipient] = GenesisAccount(
|
|
|
|
code: contractCode
|
|
|
|
)
|
|
|
|
|
2023-07-25 05:28:17 +00:00
|
|
|
if envFork >= MergeFork:
|
|
|
|
conf.networkParams.config.terminalTotalDifficulty = some(100.u256)
|
|
|
|
|
|
|
|
if envFork >= Shanghai:
|
2023-10-18 02:16:11 +00:00
|
|
|
conf.networkParams.config.shanghaiTime = some(0.EthTime)
|
2023-07-25 05:28:17 +00:00
|
|
|
|
|
|
|
if envFork >= Cancun:
|
2023-10-18 02:16:11 +00:00
|
|
|
conf.networkParams.config.cancunTime = some(0.EthTime)
|
2022-03-30 04:50:35 +00:00
|
|
|
|
|
|
|
let
|
2022-12-02 04:39:12 +00:00
|
|
|
com = CommonRef.new(
|
2024-05-20 10:17:51 +00:00
|
|
|
newCoreDbRef DefaultDbMemory,
|
2022-03-30 04:50:35 +00:00
|
|
|
conf.networkId,
|
|
|
|
conf.networkParams
|
|
|
|
)
|
2022-12-02 04:39:12 +00:00
|
|
|
chain = newChain(com)
|
2022-03-30 04:50:35 +00:00
|
|
|
|
2022-12-02 04:39:12 +00:00
|
|
|
com.initializeEmptyDb()
|
2022-03-30 04:50:35 +00:00
|
|
|
|
|
|
|
result = TestEnv(
|
|
|
|
conf: conf,
|
2022-12-02 04:39:12 +00:00
|
|
|
com: com,
|
2022-03-30 04:50:35 +00:00
|
|
|
chain: chain,
|
2024-05-30 10:11:41 +00:00
|
|
|
xp: TxPoolRef.new(com),
|
2022-03-30 04:50:35 +00:00
|
|
|
vaultKey: privKey(vaultKeyHex),
|
|
|
|
chainId: conf.networkParams.config.chainId,
|
|
|
|
nonce: 0'u64
|
|
|
|
)
|
|
|
|
|
|
|
|
const
|
|
|
|
amount = 1000.u256
|
|
|
|
slot = 0x11.u256
|
|
|
|
prevRandao = EMPTY_UNCLE_HASH # it can be any valid hash
|
|
|
|
|
2024-05-30 10:11:41 +00:00
|
|
|
proc runTxPoolPosTest() =
|
2022-03-30 04:50:35 +00:00
|
|
|
var
|
2023-07-25 05:28:17 +00:00
|
|
|
env = initEnv(MergeFork)
|
2022-03-30 04:50:35 +00:00
|
|
|
|
|
|
|
var
|
|
|
|
tx = env.makeTx(recipient, amount)
|
|
|
|
xp = env.xp
|
2022-12-02 04:39:12 +00:00
|
|
|
com = env.com
|
2022-03-30 04:50:35 +00:00
|
|
|
chain = env.chain
|
|
|
|
body: BlockBody
|
|
|
|
blk: EthBlock
|
|
|
|
|
|
|
|
suite "Test TxPool with PoS block":
|
|
|
|
test "TxPool addLocal":
|
2024-05-15 03:07:59 +00:00
|
|
|
let res = xp.addLocal(PooledTransaction(tx: tx), force = true)
|
2022-03-30 04:50:35 +00:00
|
|
|
check res.isOk
|
|
|
|
if res.isErr:
|
|
|
|
debugEcho res.error
|
|
|
|
return
|
|
|
|
|
|
|
|
test "TxPool jobCommit":
|
|
|
|
check xp.nItems.total == 1
|
|
|
|
|
|
|
|
test "TxPool ethBlock":
|
2022-12-06 05:55:40 +00:00
|
|
|
com.pos.prevRandao = prevRandao
|
|
|
|
com.pos.feeRecipient = feeRecipient
|
2023-10-18 02:16:11 +00:00
|
|
|
com.pos.timestamp = EthTime.now()
|
2022-12-06 05:55:40 +00:00
|
|
|
|
2023-11-01 02:24:32 +00:00
|
|
|
let r = xp.assembleBlock()
|
|
|
|
if r.isErr:
|
|
|
|
debugEcho r.error
|
|
|
|
check false
|
|
|
|
return
|
2022-03-30 04:50:35 +00:00
|
|
|
|
2024-05-15 03:07:59 +00:00
|
|
|
blk = r.get.blk
|
2022-12-02 04:39:12 +00:00
|
|
|
check com.isBlockAfterTtd(blk.header)
|
2022-03-30 04:50:35 +00:00
|
|
|
|
|
|
|
body = BlockBody(
|
|
|
|
transactions: blk.txs,
|
|
|
|
uncles: blk.uncles
|
|
|
|
)
|
|
|
|
check blk.txs.len == 1
|
2022-12-06 05:55:40 +00:00
|
|
|
|
2022-03-30 04:50:35 +00:00
|
|
|
test "PoS persistBlocks":
|
|
|
|
let rr = chain.persistBlocks([blk.header], [body])
|
2024-05-31 07:13:56 +00:00
|
|
|
check rr.isOk()
|
2022-03-30 04:50:35 +00:00
|
|
|
|
|
|
|
test "validate TxPool prevRandao setter":
|
2024-05-30 10:11:41 +00:00
|
|
|
var sdb = LedgerRef.init(com.db, blk.header.stateRoot)
|
|
|
|
let val = sdb.getStorage(recipient, slot)
|
2022-03-30 04:50:35 +00:00
|
|
|
let randao = Hash256(data: val.toBytesBE)
|
|
|
|
check randao == prevRandao
|
|
|
|
|
2022-04-04 02:01:39 +00:00
|
|
|
test "feeRecipient rewarded":
|
|
|
|
check blk.header.coinbase == feeRecipient
|
2024-05-30 10:11:41 +00:00
|
|
|
var sdb = LedgerRef.init(com.db, blk.header.stateRoot)
|
2022-04-04 02:01:39 +00:00
|
|
|
let bal = sdb.getBalance(feeRecipient)
|
|
|
|
check not bal.isZero
|
|
|
|
|
2024-05-30 10:11:41 +00:00
|
|
|
proc runTxPoolBlobhashTest() =
|
2023-07-25 05:28:17 +00:00
|
|
|
var
|
|
|
|
env = initEnv(Cancun)
|
|
|
|
|
|
|
|
var
|
2023-08-04 03:59:12 +00:00
|
|
|
tx1 = env.makeTx(recipient, amount)
|
|
|
|
tx2 = env.makeTx(recipient, amount)
|
2023-07-25 05:28:17 +00:00
|
|
|
xp = env.xp
|
|
|
|
com = env.com
|
|
|
|
chain = env.chain
|
|
|
|
body: BlockBody
|
|
|
|
blk: EthBlock
|
|
|
|
|
|
|
|
suite "Test TxPool with blobhash block":
|
|
|
|
test "TxPool addLocal":
|
2024-05-15 03:07:59 +00:00
|
|
|
let res = xp.addLocal(PooledTransaction(tx: tx1), force = true)
|
2023-07-25 05:28:17 +00:00
|
|
|
check res.isOk
|
|
|
|
if res.isErr:
|
|
|
|
debugEcho res.error
|
|
|
|
return
|
2024-05-15 03:07:59 +00:00
|
|
|
let res2 = xp.addLocal(PooledTransaction(tx: tx2), force = true)
|
2023-08-04 03:59:12 +00:00
|
|
|
check res2.isOk
|
2023-07-25 05:28:17 +00:00
|
|
|
|
|
|
|
test "TxPool jobCommit":
|
2023-08-04 03:59:12 +00:00
|
|
|
check xp.nItems.total == 2
|
2023-07-25 05:28:17 +00:00
|
|
|
|
|
|
|
test "TxPool ethBlock":
|
|
|
|
com.pos.prevRandao = prevRandao
|
|
|
|
com.pos.feeRecipient = feeRecipient
|
2023-10-18 02:16:11 +00:00
|
|
|
com.pos.timestamp = EthTime.now()
|
2023-07-25 05:28:17 +00:00
|
|
|
|
2023-11-01 02:24:32 +00:00
|
|
|
let r = xp.assembleBlock()
|
|
|
|
if r.isErr:
|
|
|
|
debugEcho r.error
|
|
|
|
check false
|
|
|
|
return
|
2023-07-25 05:28:17 +00:00
|
|
|
|
2024-05-15 03:07:59 +00:00
|
|
|
blk = r.get.blk
|
2023-07-25 05:28:17 +00:00
|
|
|
check com.isBlockAfterTtd(blk.header)
|
|
|
|
|
|
|
|
body = BlockBody(
|
|
|
|
transactions: blk.txs,
|
|
|
|
uncles: blk.uncles,
|
|
|
|
withdrawals: some[seq[Withdrawal]](@[])
|
|
|
|
)
|
2023-08-04 03:59:12 +00:00
|
|
|
check blk.txs.len == 2
|
2023-07-25 05:28:17 +00:00
|
|
|
|
|
|
|
test "Blobhash persistBlocks":
|
|
|
|
let rr = chain.persistBlocks([blk.header], [body])
|
2024-05-31 07:13:56 +00:00
|
|
|
check rr.isOk()
|
2023-07-25 05:28:17 +00:00
|
|
|
|
|
|
|
test "validate TxPool prevRandao setter":
|
2024-05-30 10:11:41 +00:00
|
|
|
var sdb = LedgerRef.init(com.db, blk.header.stateRoot)
|
|
|
|
let val = sdb.getStorage(recipient, slot)
|
2023-07-25 05:28:17 +00:00
|
|
|
let randao = Hash256(data: val.toBytesBE)
|
|
|
|
check randao == prevRandao
|
|
|
|
|
|
|
|
test "feeRecipient rewarded":
|
|
|
|
check blk.header.coinbase == feeRecipient
|
2024-05-30 10:11:41 +00:00
|
|
|
var sdb = LedgerRef.init(com.db, blk.header.stateRoot)
|
2023-07-25 05:28:17 +00:00
|
|
|
let bal = sdb.getBalance(feeRecipient)
|
|
|
|
check not bal.isZero
|
|
|
|
|
2023-08-04 03:59:12 +00:00
|
|
|
test "add tx with nonce too low":
|
|
|
|
let
|
|
|
|
tx3 = env.makeTx(recipient, amount)
|
|
|
|
tx4 = env.signTxWithNonce(tx3, AccountNonce(env.nonce-2))
|
|
|
|
xp = env.xp
|
|
|
|
|
|
|
|
check xp.smartHead(blk.header)
|
2024-05-15 03:07:59 +00:00
|
|
|
let res = xp.addLocal(PooledTransaction(tx: tx4), force = true)
|
2023-08-04 03:59:12 +00:00
|
|
|
check res.isOk
|
|
|
|
if res.isErr:
|
|
|
|
debugEcho res.error
|
|
|
|
return
|
|
|
|
|
|
|
|
check inPoolAndOk(xp, rlpHash(tx4)) == false
|
|
|
|
|
2024-05-30 10:11:41 +00:00
|
|
|
proc runTxHeadDelta(noisy = true) =
|
2022-04-04 08:34:59 +00:00
|
|
|
## see github.com/status-im/nimbus-eth1/issues/1031
|
|
|
|
|
2022-04-04 15:56:21 +00:00
|
|
|
suite "TxPool: Synthesising blocks (covers issue #1031)":
|
|
|
|
test "Packing and adding multiple blocks to chain":
|
2022-04-04 08:34:59 +00:00
|
|
|
var
|
2023-07-25 05:28:17 +00:00
|
|
|
env = initEnv(MergeFork)
|
2022-04-04 08:34:59 +00:00
|
|
|
xp = env.xp
|
2022-12-02 04:39:12 +00:00
|
|
|
com = env.com
|
2022-04-04 08:34:59 +00:00
|
|
|
chain = env.chain
|
2022-12-02 04:39:12 +00:00
|
|
|
head = com.db.getCanonicalHead()
|
2022-04-04 08:34:59 +00:00
|
|
|
timestamp = head.timestamp
|
|
|
|
|
|
|
|
const
|
|
|
|
txPerblock = 20
|
|
|
|
numBlocks = 10
|
|
|
|
|
|
|
|
# setTraceLevel()
|
|
|
|
|
2022-04-08 14:05:30 +00:00
|
|
|
block:
|
2022-04-04 08:34:59 +00:00
|
|
|
for n in 0..<numBlocks:
|
|
|
|
|
|
|
|
for tn in 0..<txPerblock:
|
|
|
|
let tx = env.makeTx(recipient, amount)
|
2022-04-08 14:05:30 +00:00
|
|
|
# Instead of `add()`, the functions `addRemote()` or `addLocal()`
|
|
|
|
# also would do.
|
2024-05-15 03:07:59 +00:00
|
|
|
xp.add(PooledTransaction(tx: tx))
|
2022-04-04 08:34:59 +00:00
|
|
|
|
2022-04-04 15:56:21 +00:00
|
|
|
noisy.say "***", "txDB",
|
2022-04-04 08:34:59 +00:00
|
|
|
&" n={n}",
|
2022-04-04 15:56:21 +00:00
|
|
|
# pending/staged/packed : total/disposed
|
|
|
|
&" stats={xp.nItems.pp}"
|
2022-04-04 08:34:59 +00:00
|
|
|
|
2023-10-18 02:16:11 +00:00
|
|
|
timestamp = timestamp + 1
|
2022-12-06 05:55:40 +00:00
|
|
|
com.pos.prevRandao = prevRandao
|
|
|
|
com.pos.timestamp = timestamp
|
|
|
|
com.pos.feeRecipient = feeRecipient
|
|
|
|
|
2023-11-01 02:24:32 +00:00
|
|
|
let r = xp.assembleBlock()
|
|
|
|
if r.isErr:
|
|
|
|
debugEcho r.error
|
|
|
|
check false
|
|
|
|
return
|
|
|
|
|
2024-05-15 03:07:59 +00:00
|
|
|
let blk = r.get.blk
|
2022-12-02 04:39:12 +00:00
|
|
|
check com.isBlockAfterTtd(blk.header)
|
2022-04-04 08:34:59 +00:00
|
|
|
|
|
|
|
let body = BlockBody(
|
|
|
|
transactions: blk.txs,
|
|
|
|
uncles: blk.uncles)
|
|
|
|
|
2022-04-04 15:56:21 +00:00
|
|
|
# Commit to block chain
|
|
|
|
check chain.persistBlocks([blk.header], [body]).isOk
|
2022-04-04 08:34:59 +00:00
|
|
|
|
2022-04-04 15:56:21 +00:00
|
|
|
# Synchronise TxPool against new chain head, register txs differences.
|
|
|
|
# In this particular case, these differences will simply flush the
|
|
|
|
# packer bucket.
|
2022-04-08 14:05:30 +00:00
|
|
|
check xp.smartHead(blk.header)
|
2022-04-04 15:56:21 +00:00
|
|
|
|
|
|
|
# Move TxPool chain head to new chain head and apply delta jobs
|
|
|
|
check xp.nItems.staged == 0
|
|
|
|
check xp.nItems.packed == 0
|
|
|
|
|
|
|
|
setErrorLevel() # in case we set trace level
|
2022-04-04 08:34:59 +00:00
|
|
|
|
2022-12-02 04:39:12 +00:00
|
|
|
check com.syncCurrent == 10.toBlockNumber
|
|
|
|
head = com.db.getBlockHeader(com.syncCurrent)
|
2022-04-04 08:34:59 +00:00
|
|
|
let
|
2024-05-30 10:11:41 +00:00
|
|
|
sdb = LedgerRef.init(com.db, head.stateRoot)
|
2022-04-04 08:34:59 +00:00
|
|
|
expected = u256(txPerblock * numBlocks) * amount
|
|
|
|
balance = sdb.getBalance(recipient)
|
|
|
|
check balance == expected
|
|
|
|
|
2024-05-30 10:11:41 +00:00
|
|
|
proc txPool2Main*() =
|
2022-04-04 08:34:59 +00:00
|
|
|
const
|
|
|
|
noisy = defined(debug)
|
|
|
|
|
|
|
|
setErrorLevel() # mute logger
|
|
|
|
|
2023-07-25 05:28:17 +00:00
|
|
|
runTxPoolPosTest()
|
|
|
|
runTxPoolBlobhashTest()
|
2024-05-30 10:11:41 +00:00
|
|
|
noisy.runTxHeadDelta
|
|
|
|
|
|
|
|
when isMainModule:
|
|
|
|
txPool2Main()
|
2022-04-04 08:34:59 +00:00
|
|
|
|
2022-04-08 14:05:30 +00:00
|
|
|
# End
|