diff --git a/src/testing/testing_commitBlockV1.yaml b/src/testing/testing_commitBlockV1.yaml new file mode 100644 index 000000000..62bc0820a --- /dev/null +++ b/src/testing/testing_commitBlockV1.yaml @@ -0,0 +1,87 @@ +- name: testing_commitBlockV1 + summary: Builds a block from the provided parameters, inserts it into the chain, and sets it as the canonical head. This is a testing-only method for advancing a chain deterministically. + description: | + This method is a testing tool that combines block production and canonical head advancement into a single call. It is the writing equivalent of [`testing_buildBlockV1`](./testing_buildBlockV1.yaml): it produces the same block, but additionally inserts it into the chain and sets it as the new canonical head, skipping the `engine_newPayload` + `engine_forkchoiceUpdated` round-trip and the associated payload serialization overhead. + + **Specification:** + - The client MUST build a new execution payload on top of its current canonical head. + - The client MUST use the provided `payloadAttributes` to define the context of the new block. + - If the `transactions` parameter is an empty array `[]`, the client MUST build an empty block (no transactions). + - If the `transactions` parameter is JSON `null`, the client MAY build a block from its local transaction pool (mempool). + - If the `transactions` parameter is a non-empty array, the client MUST include all transactions from the array on the block's transaction list, in the order they were provided, and MUST NOT include any transactions from its local transaction pool. + - If `extraData` is provided, the client MUST set the `extraData` field of the resulting block to this value. + - On success, the client MUST insert the block into its database, set it as the canonical head, emit the same chain events it would for any new head, and return the new head's block hash. + - If the block cannot be built or applied (for example, an unapplicable transaction), the client MUST return a JSON-RPC error and MUST NOT modify the canonical head. + + **Security Considerations:** + - This method is intended for testing environments ONLY and MUST NOT be exposed on public-facing RPC APIs. + - It is strongly recommended that this method be disabled by default. + params: + - name: Payload attributes + required: true + schema: + title: PayloadAttributesV3 + type: object + properties: + timestamp: + $ref: '#/components/schemas/uint' + prevRandao: + $ref: '#/components/schemas/hash32' + suggestedFeeRecipient: + $ref: '#/components/schemas/address' + withdrawals: + title: Withdrawals + type: array + items: + $ref: '#/components/schemas/Withdrawal' + parentBeaconBlockRoot: + $ref: '#/components/schemas/hash32' + - name: Transactions + required: true + description: | + An array of raw, signed transactions (hex-encoded) to include in the committed block, or null. + - If an empty array `[]`: The client MUST build an empty block (no transactions). + - If `null`: The client MAY build a block from its local transaction pool (mempool). + - If a non-empty array: The client MUST include ALL transactions from this array in the resulting block, in the order provided, and MUST NOT include any transactions from its local mempool. + schema: + title: Transactions + oneOf: + - type: array + items: + $ref: '#/components/schemas/bytes' + - type: 'null' + - name: Extra data + required: false + description: | + Data to be set as the extraData field of the committed block. If provided, the client MUST use this exact value. + schema: + oneOf: + - $ref: '#/components/schemas/bytes' + - type: 'null' + result: + name: Block hash + schema: + title: Committed block hash + $ref: '#/components/schemas/hash32' + errors: + - code: -32602 + message: Invalid parameters + - code: -32603 + message: Internal error + examples: + - name: testing_commitBlockV1 example + params: + - name: Payload attributes + value: + timestamp: '0x1ce' + prevRandao: '0x0000000000000000000000000000000000000000000000000000000000000000' + suggestedFeeRecipient: '0x0000000000000000000000000000000000000000' + withdrawals: [] + parentBeaconBlockRoot: '0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822' + - name: Transactions + value: [] + - name: Extra data + value: null + result: + name: Block hash + value: '0x1234567890123456789012345678901234567890123456789012345678901234' diff --git a/tests/forkenv.json b/tests/forkenv.json index 3da235343..2e1f5e85f 100644 --- a/tests/forkenv.json +++ b/tests/forkenv.json @@ -18,6 +18,7 @@ "HIVE_FORK_TANGERINE": "3", "HIVE_MERGE_BLOCK_ID": "36", "HIVE_NETWORK_ID": "3503995874084926", + "HIVE_TARGET_GAS_LIMIT": "60000000", "HIVE_PRAGUE_BLOB_BASE_FEE_UPDATE_FRACTION": "5007716", "HIVE_PRAGUE_BLOB_MAX": "9", "HIVE_PRAGUE_BLOB_TARGET": "6", diff --git a/tests/testing_commitBlockV1/commit-block-empty-transactions.io b/tests/testing_commitBlockV1/commit-block-empty-transactions.io new file mode 100644 index 000000000..d7fbab122 --- /dev/null +++ b/tests/testing_commitBlockV1/commit-block-empty-transactions.io @@ -0,0 +1,7 @@ +// commits an empty block using testing_commitBlockV1 and advances the canonical head +>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":1,"result":{"baseFeePerGas":"0x5763d64","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x","gasLimit":"0x47e7c40","gasUsed":"0x54a92","hash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","logsBloom":"0x00000000008000000000000000000040000000000000000000000000800000000000000008000000000000000000000000000000000000000000000000000000000000000000000000004000000000020200000000000000000000000000002000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","number":"0x2d","parentBeaconBlockRoot":"0x4b118bd31ed2c4eeb81dc9e3919e9989994333fe36f147c2930f12c53f0d3c78","parentHash":"0x4b9d85c6787612e87e0659e11a347d415040465e492358f79cc7e2e293f38aa7","receiptsRoot":"0x2c86b2791cdd088d3c3e9d6225f71724d3e8c67bdd13cd6208831058cee1043f","requestsHash":"0x57cac3e52cdcd73e52bd9e54956e0eae370f00ed41f68edc78266bdb46c3a543","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x633","stateRoot":"0xf61892bbb9a9df427d1f941dc8c536d72c41efed598244726ea21a0f183ff232","timestamp":"0x1c2","transactions":[{"blockHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","blockNumber":"0x2d","blockTimestamp":"0x1c2","from":"0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f","gas":"0x11c32","gasPrice":"0x5763d65","hash":"0x2fbbd036996c7487316c92b9e5798edb98fd57f32a6c1075e904a734821e1cd2","input":"0x600d380380600d6000396000f336156009575f355f555b305f525f5460205260405ff3","nonce":"0x9a","to":null,"transactionIndex":"0x0","value":"0x0","type":"0x0","chainId":"0xc72dd9d5e883e","v":"0x18e5bb3abd109f","r":"0x551fe45ccebb0318196e31dbc60da87c43dc60b8fb01afb3286693fa09878730","s":"0x40d33e9afecfe1516b045d61a3272bddbc83f482a7f2c749311248b50fe62e81"},{"blockHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","blockNumber":"0x2d","blockTimestamp":"0x1c2","from":"0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f","gas":"0xb3b0","gasPrice":"0x5763d65","maxFeePerGas":"0x5763d65","maxPriorityFeePerGas":"0x1","hash":"0x16f6724ad864e7664c367893cae3e176d362bea3a47495cec3b246555a7228da","input":"0x","nonce":"0x9b","to":"0x0000000000000000000000000000000000000000","transactionIndex":"0x1","value":"0x0","type":"0x4","accessList":[],"chainId":"0xc72dd9d5e883e","authorizationList":[{"chainId":"0xc72dd9d5e883e","address":"0x58f8fe237b593c19546e1e758a2544561d04bfe0","nonce":"0x0","yParity":"0x1","r":"0xec6caeb1b7071f1b3ae36aeaa7bf0eaecb8e006e83b3e50d792870ea95af4c59","s":"0x1d1225f76d6faac3d904c0635193e83d3867c101b2e6f6c9bb7b1fdeeed923ab"}],"v":"0x1","r":"0x8ae3402e4f63751c895532b94aee0f7b6b8ff5d0b0a689f6d63b3dbd19d69059","s":"0x2e63e4d140b0d282d56289b34f3df82cbcb2f3aa385f5438a423584fe0c2b467","yParity":"0x1"},{"blockHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","blockNumber":"0x2d","blockTimestamp":"0x1c2","from":"0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f","gas":"0x11170","gasPrice":"0x5763d65","hash":"0xddf234c5f149d2d1a4d01276d42e38a6234bfa7b987c49ba889b028b429aac8f","input":"0x696e766f6b6564","nonce":"0x9c","to":"0xeda8645ba6948855e3b3cd596bbb07596d59c603","transactionIndex":"0x2","value":"0x0","type":"0x0","chainId":"0xc72dd9d5e883e","v":"0x18e5bb3abd10a0","r":"0xfea7e18c82a1270f142572533bc2e6e33d6d41a3f1303403dd0a90dd7a4f35d","s":"0x4a4ab6c5bb4c31c3a5f8991ae45bad2303c45923404571f7b4c66adbd03b7936"},{"blockHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","blockNumber":"0x2d","blockTimestamp":"0x1c2","from":"0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f","gas":"0x249f0","gasPrice":"0x5763d65","maxFeePerGas":"0x5763d65","maxPriorityFeePerGas":"0x2","hash":"0x3d3d02e1bdc39a6eab20f7b44ed299ca61eb1d642806bfa07e3a7ee8edd700e5","input":"0xb917cfdc0d25b72d55cf94db328e1629b7f4fde2c30cdacf873b664416f76a0c7f7cc50c9f72a3cb84be88144cde91250000000000000d80","nonce":"0x9d","to":"0x00000961ef480eb55e80d19ad83579a64c007002","transactionIndex":"0x3","value":"0x3b9aca00","type":"0x2","accessList":[],"chainId":"0xc72dd9d5e883e","v":"0x1","r":"0x5f8b300cf80f7fb7e511460fa1a803278b47223f2c0a82857c5c0e5f7c900d23","s":"0x290bf2495235a106352786403ed937df8385a2356472569020fd952913690ec9","yParity":"0x1"},{"blockHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","blockNumber":"0x2d","blockTimestamp":"0x1c2","from":"0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f","gas":"0x186a0","gasPrice":"0x5763d65","hash":"0x195a09414344f56e7a202d1493b258b2394b9b93811ce4ee96212a7d34ffb04f","input":"0x6b3b937565afc29f656d6974","nonce":"0x9e","to":"0x7dcd17433742f4c0ca53122ab541d0ba67fc27df","transactionIndex":"0x4","value":"0x2","type":"0x1","accessList":[{"address":"0x7dcd17433742f4c0ca53122ab541d0ba67fc27df","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000000","0xe8481f0a1ea7b2528784efff1d1b33cbd66ac97ebe2ae35c7997cacb2863430b"]}],"chainId":"0xc72dd9d5e883e","v":"0x0","r":"0x84f8b48ac6fbf39054c7794e6ff4e16a3bacbd0964b53d4d03ff668e7eda365","s":"0x2e4e86f2f5fbb8dad4ee8907eee4488f70c75bb646522b5197c4dcdc29ea31bf","yParity":"0x0"},{"blockHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","blockNumber":"0x2d","blockTimestamp":"0x1c2","from":"0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f","gas":"0x5208","gasPrice":"0x5763d65","hash":"0xdf66bea01c5cf47b48ec11453822d751a5daaf1d16959772c2196c5ab8cf8438","input":"0x","nonce":"0x9f","to":"0x4340ee1b812acb40a1eb561c019c327b243b92df","transactionIndex":"0x5","value":"0x1","type":"0x1","accessList":[],"chainId":"0xc72dd9d5e883e","v":"0x1","r":"0xec839e20a6f8ff0fb1043022e5816454191436ba7f6607bf6efe6517fdd1e2dd","s":"0x7903b3dd48963c0404f99807fd89cde2b66091c32178f66920120cb10981019","yParity":"0x1"}],"transactionsRoot":"0xc541c333ff4a96a17d3601f7d628ea27ecf4597a11077e5d9d1c4dbed6c7f401","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} +>> {"jsonrpc":"2.0","id":2,"method":"testing_commitBlockV1","params":[{"parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","prevRandao":"0x1111111111111111111111111111111111111111111111111111111111111111","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","timestamp":"0x1ce","withdrawals":[]},[],"0x"]} +<< {"jsonrpc":"2.0","id":2,"result":"0xf716541a4f889e10bf75f9796cc8212f6868f138c6a1c589008d33197edb19b7"} +>> {"jsonrpc":"2.0","id":3,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":3,"result":{"baseFeePerGas":"0x4c9114a","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x","gasLimit":"0x47d5ca2","gasUsed":"0x0","hash":"0xf716541a4f889e10bf75f9796cc8212f6868f138c6a1c589008d33197edb19b7","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x2e","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x266","stateRoot":"0x4c6709fca84ff2bcca8609b4a54cb96fc1c001862d450d334088cd5694cad374","timestamp":"0x1ce","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} diff --git a/tests/testing_commitBlockV1/commit-block-invalid-transaction.io b/tests/testing_commitBlockV1/commit-block-invalid-transaction.io new file mode 100644 index 000000000..59a8cb303 --- /dev/null +++ b/tests/testing_commitBlockV1/commit-block-invalid-transaction.io @@ -0,0 +1,7 @@ +// calls testing_commitBlockV1 with an unapplicable transaction (wrong nonce); client MUST return an error and not modify the canonical head +>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":1,"result":{"baseFeePerGas":"0x4c9114a","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x","gasLimit":"0x47d5ca2","gasUsed":"0x0","hash":"0xf716541a4f889e10bf75f9796cc8212f6868f138c6a1c589008d33197edb19b7","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x2e","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x266","stateRoot":"0x4c6709fca84ff2bcca8609b4a54cb96fc1c001862d450d334088cd5694cad374","timestamp":"0x1ce","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} +>> {"jsonrpc":"2.0","id":2,"method":"testing_commitBlockV1","params":[{"parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","prevRandao":"0x1111111111111111111111111111111111111111111111111111111111111111","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","timestamp":"0x1da","withdrawals":[]},["0x02f873870c72dd9d5e883e8203e78201f48404c9133e825208947dcd17433742f4c0ca53122ab541d0ba67fc27df8203e880c001a0c8b048f65d5225e1418625c96e146fb671f998da69a420371ce233a6c2d3759ba0106de16d8d9e4de84ee0012baaca7e94d9d4b82a1b2dbade8a50818b78ada7d1"],"0x"]} +<< {"jsonrpc":"2.0","id":2,"error":{"code":-32000,"message":"nonce too high: address 0x16c57eDF7Fa9D9525378B0b81Bf8A3cEd0620C1c, tx: 999 state: 0"}} +>> {"jsonrpc":"2.0","id":3,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":3,"result":{"baseFeePerGas":"0x4c9114a","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x","gasLimit":"0x47d5ca2","gasUsed":"0x0","hash":"0xf716541a4f889e10bf75f9796cc8212f6868f138c6a1c589008d33197edb19b7","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x2e","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x266","stateRoot":"0x4c6709fca84ff2bcca8609b4a54cb96fc1c001862d450d334088cd5694cad374","timestamp":"0x1ce","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} diff --git a/tests/testing_commitBlockV1/commit-block-with-extra-data.io b/tests/testing_commitBlockV1/commit-block-with-extra-data.io new file mode 100644 index 000000000..32f06c7a1 --- /dev/null +++ b/tests/testing_commitBlockV1/commit-block-with-extra-data.io @@ -0,0 +1,7 @@ +// commits a block with a non-empty extraData value using testing_commitBlockV1 +>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":1,"result":{"baseFeePerGas":"0x4c9114a","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x","gasLimit":"0x47d5ca2","gasUsed":"0x0","hash":"0xf716541a4f889e10bf75f9796cc8212f6868f138c6a1c589008d33197edb19b7","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x2e","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0xe27a3e81bd7cfe2aec2cc9e832c73a17c93e7efcf659cf4b39883b96c48708c2","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x266","stateRoot":"0x4c6709fca84ff2bcca8609b4a54cb96fc1c001862d450d334088cd5694cad374","timestamp":"0x1ce","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} +>> {"jsonrpc":"2.0","id":2,"method":"testing_commitBlockV1","params":[{"parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","prevRandao":"0x1111111111111111111111111111111111111111111111111111111111111111","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","timestamp":"0x1da","withdrawals":[]},[],"0x657865637574696f6e2d61706973"]} +<< {"jsonrpc":"2.0","id":2,"result":"0x2676f95f2fbac4fbee8ef8c43db1d60271d4e62fb248977231a1238af9913b83"} +>> {"jsonrpc":"2.0","id":3,"method":"eth_getBlockByHash","params":["0x2676f95f2fbac4fbee8ef8c43db1d60271d4e62fb248977231a1238af9913b83",true]} +<< {"jsonrpc":"2.0","id":3,"result":{"baseFeePerGas":"0x42fef21","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x657865637574696f6e2d61706973","gasLimit":"0x47c3d4c","gasUsed":"0x0","hash":"0x2676f95f2fbac4fbee8ef8c43db1d60271d4e62fb248977231a1238af9913b83","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x2f","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0xf716541a4f889e10bf75f9796cc8212f6868f138c6a1c589008d33197edb19b7","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x274","stateRoot":"0x73ac65ec5d8bbda83a9afb4e0f86862fbc5a456eb144d68d14434c56f495dcd3","timestamp":"0x1da","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} diff --git a/tests/testing_commitBlockV1/commit-block-with-transactions.io b/tests/testing_commitBlockV1/commit-block-with-transactions.io new file mode 100644 index 000000000..8fb1eba5a --- /dev/null +++ b/tests/testing_commitBlockV1/commit-block-with-transactions.io @@ -0,0 +1,9 @@ +// commits a block with the specified transactions using testing_commitBlockV1 and advances the canonical head +>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":1,"result":{"baseFeePerGas":"0x42fef21","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x657865637574696f6e2d61706973","gasLimit":"0x47c3d4c","gasUsed":"0x0","hash":"0x2676f95f2fbac4fbee8ef8c43db1d60271d4e62fb248977231a1238af9913b83","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x2f","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0xf716541a4f889e10bf75f9796cc8212f6868f138c6a1c589008d33197edb19b7","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x274","stateRoot":"0x73ac65ec5d8bbda83a9afb4e0f86862fbc5a456eb144d68d14434c56f495dcd3","timestamp":"0x1da","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} +>> {"jsonrpc":"2.0","id":2,"method":"testing_commitBlockV1","params":[{"parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","prevRandao":"0x1111111111111111111111111111111111111111111111111111111111111111","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","timestamp":"0x1e6","withdrawals":[]},["0x02f871870c72dd9d5e883e808201f484042ff115825208947dcd17433742f4c0ca53122ab541d0ba67fc27df8203e880c001a08c217df89f8b7041a374bf747dfb3ee0a09542c5794941bc154f498a0533ae29a0099a2ce7c3fa81b418bdb0e0ebb643f2ee5d6ec791e379d957cfaf2037727b33"],"0x746573745f6e616d65"]} +<< {"jsonrpc":"2.0","id":2,"result":"0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe"} +>> {"jsonrpc":"2.0","id":3,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":3,"result":{"baseFeePerGas":"0x3a9f13d","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x746573745f6e616d65","gasLimit":"0x47b1e3e","gasUsed":"0x5208","hash":"0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x30","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0x2676f95f2fbac4fbee8ef8c43db1d60271d4e62fb248977231a1238af9913b83","receiptsRoot":"0x005fb2a0d0c8a6f3490f9594e6458703eea515262f1b69a1103492b61e8d0ee2","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x2e8","stateRoot":"0xcd29915bf19a7c4eb3558c8dda426e1281af3d1e63588cac64c81bf1a04aa26d","timestamp":"0x1e6","transactions":[{"blockHash":"0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe","blockNumber":"0x30","blockTimestamp":"0x1e6","from":"0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c","gas":"0x5208","gasPrice":"0x3a9f331","maxFeePerGas":"0x42ff115","maxPriorityFeePerGas":"0x1f4","hash":"0xfc96e88d69d9b1a5f82262e26bba9f3b00abc73650af6c0a78550055bbda7658","input":"0x","nonce":"0x0","to":"0x7dcd17433742f4c0ca53122ab541d0ba67fc27df","transactionIndex":"0x0","value":"0x3e8","type":"0x2","accessList":[],"chainId":"0xc72dd9d5e883e","v":"0x1","r":"0x8c217df89f8b7041a374bf747dfb3ee0a09542c5794941bc154f498a0533ae29","s":"0x99a2ce7c3fa81b418bdb0e0ebb643f2ee5d6ec791e379d957cfaf2037727b33","yParity":"0x1"}],"transactionsRoot":"0xfab5526d3df2b967ca0b1a613a9c13f7aee56bfc295e5b4f903b834460fc5f72","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} +>> {"jsonrpc":"2.0","id":4,"method":"eth_getBlockByHash","params":["0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe",true]} +<< {"jsonrpc":"2.0","id":4,"result":{"baseFeePerGas":"0x3a9f13d","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x746573745f6e616d65","gasLimit":"0x47b1e3e","gasUsed":"0x5208","hash":"0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x30","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0x2676f95f2fbac4fbee8ef8c43db1d60271d4e62fb248977231a1238af9913b83","receiptsRoot":"0x005fb2a0d0c8a6f3490f9594e6458703eea515262f1b69a1103492b61e8d0ee2","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x2e8","stateRoot":"0xcd29915bf19a7c4eb3558c8dda426e1281af3d1e63588cac64c81bf1a04aa26d","timestamp":"0x1e6","transactions":[{"blockHash":"0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe","blockNumber":"0x30","blockTimestamp":"0x1e6","from":"0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c","gas":"0x5208","gasPrice":"0x3a9f331","maxFeePerGas":"0x42ff115","maxPriorityFeePerGas":"0x1f4","hash":"0xfc96e88d69d9b1a5f82262e26bba9f3b00abc73650af6c0a78550055bbda7658","input":"0x","nonce":"0x0","to":"0x7dcd17433742f4c0ca53122ab541d0ba67fc27df","transactionIndex":"0x0","value":"0x3e8","type":"0x2","accessList":[],"chainId":"0xc72dd9d5e883e","v":"0x1","r":"0x8c217df89f8b7041a374bf747dfb3ee0a09542c5794941bc154f498a0533ae29","s":"0x99a2ce7c3fa81b418bdb0e0ebb643f2ee5d6ec791e379d957cfaf2037727b33","yParity":"0x1"}],"transactionsRoot":"0xfab5526d3df2b967ca0b1a613a9c13f7aee56bfc295e5b4f903b834460fc5f72","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} diff --git a/tests/testing_commitBlockV1/commit-block-z-from-mempool.io b/tests/testing_commitBlockV1/commit-block-z-from-mempool.io new file mode 100644 index 000000000..3cda05ff2 --- /dev/null +++ b/tests/testing_commitBlockV1/commit-block-z-from-mempool.io @@ -0,0 +1,10 @@ +// commits a block built from the mempool using testing_commitBlockV1 with null transactions parameter +// speconly: client response is only checked for schema validity. +>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":1,"result":{"baseFeePerGas":"0x3a9f13d","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x746573745f6e616d65","gasLimit":"0x47b1e3e","gasUsed":"0x5208","hash":"0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x30","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0x2676f95f2fbac4fbee8ef8c43db1d60271d4e62fb248977231a1238af9913b83","receiptsRoot":"0x005fb2a0d0c8a6f3490f9594e6458703eea515262f1b69a1103492b61e8d0ee2","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x2e8","stateRoot":"0xcd29915bf19a7c4eb3558c8dda426e1281af3d1e63588cac64c81bf1a04aa26d","timestamp":"0x1e6","transactions":[{"blockHash":"0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe","blockNumber":"0x30","blockTimestamp":"0x1e6","from":"0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c","gas":"0x5208","gasPrice":"0x3a9f331","maxFeePerGas":"0x42ff115","maxPriorityFeePerGas":"0x1f4","hash":"0xfc96e88d69d9b1a5f82262e26bba9f3b00abc73650af6c0a78550055bbda7658","input":"0x","nonce":"0x0","to":"0x7dcd17433742f4c0ca53122ab541d0ba67fc27df","transactionIndex":"0x0","value":"0x3e8","type":"0x2","accessList":[],"chainId":"0xc72dd9d5e883e","v":"0x1","r":"0x8c217df89f8b7041a374bf747dfb3ee0a09542c5794941bc154f498a0533ae29","s":"0x99a2ce7c3fa81b418bdb0e0ebb643f2ee5d6ec791e379d957cfaf2037727b33","yParity":"0x1"}],"transactionsRoot":"0xfab5526d3df2b967ca0b1a613a9c13f7aee56bfc295e5b4f903b834460fc5f72","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} +>> {"jsonrpc":"2.0","id":2,"method":"eth_sendRawTransaction","params":["0x02f871870c72dd9d5e883e808201f48403a9f331825208947dcd17433742f4c0ca53122ab541d0ba67fc27df8203e880c080a00b07a6d14f7fa9e35e11f88078ff65d86b25843106fd098334b4c37de9e7c89ba048faa649364600bacc4c5a58bc8e263bf34f4fd041e2dde0c35f51e3b4e220f7"]} +<< {"jsonrpc":"2.0","id":2,"result":"0x5970edd3114a7fe94251cfe4853e54c320bf72c54f876fbd6bc062b2e053525a"} +>> {"jsonrpc":"2.0","id":3,"method":"testing_commitBlockV1","params":[{"parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","prevRandao":"0x1111111111111111111111111111111111111111111111111111111111111111","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","timestamp":"0x1f2","withdrawals":[]},null,"0x"]} +<< {"jsonrpc":"2.0","id":3,"result":"0x32d8a312839bb022b0a4f7626103a394e5a4db0eef333998b99de37bd9cd8b46"} +>> {"jsonrpc":"2.0","id":4,"method":"eth_getBlockByNumber","params":["latest",true]} +<< {"jsonrpc":"2.0","id":4,"result":{"baseFeePerGas":"0x334c3db","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x","gasLimit":"0x479ff78","gasUsed":"0x0","hash":"0x32d8a312839bb022b0a4f7626103a394e5a4db0eef333998b99de37bd9cd8b46","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"0x0000000000000000","number":"0x31","parentBeaconBlockRoot":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822","parentHash":"0xff580b04a9b17f9a9271b88c6eab3139f4a965de24a08c9c4eea222a9d0ae6fe","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x266","stateRoot":"0x48d1789ca87c36e3baeb94ba2c63a90b003835559a0daa8f46e4f78ce8dc6c70","timestamp":"0x1f2","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[],"withdrawals":[],"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}} diff --git a/tools/chain/forkenv.json b/tools/chain/forkenv.json index 3da235343..2e1f5e85f 100644 --- a/tools/chain/forkenv.json +++ b/tools/chain/forkenv.json @@ -18,6 +18,7 @@ "HIVE_FORK_TANGERINE": "3", "HIVE_MERGE_BLOCK_ID": "36", "HIVE_NETWORK_ID": "3503995874084926", + "HIVE_TARGET_GAS_LIMIT": "60000000", "HIVE_PRAGUE_BLOB_BASE_FEE_UPDATE_FRACTION": "5007716", "HIVE_PRAGUE_BLOB_MAX": "9", "HIVE_PRAGUE_BLOB_TARGET": "6", diff --git a/tools/testgen/generators.go b/tools/testgen/generators.go index 94e9dca68..b94f7fd8a 100644 --- a/tools/testgen/generators.go +++ b/tools/testgen/generators.go @@ -93,6 +93,13 @@ var AllMethods = []MethodTests{ EthBlobBaseFee, NetVersion, TestingBuildBlockV1, + + // testing_commitBlockV1 must come before txpool_* so that fill order matches + // hive's lexical replay order (testing_buildBlockV1, testing_commitBlockV1, + // txpool_*). It advances the canonical head, so it must also come after every + // read-only test that assumes the static chain head. + TestingCommitBlockV1, + TxpoolStatus, TxpoolContent, TxpoolContentFrom, @@ -2798,6 +2805,326 @@ var TestingBuildBlockV1 = MethodTests{ }, } +// commitBlockV1PayloadAttrs returns a payloadAttributes map suitable for committing a +// block on top of parentBlock. Cancun-only fields are included when active. +func commitBlockV1PayloadAttrs(t *T, parentBlock *types.Block, salt string) map[string]interface{} { + attrs := map[string]interface{}{ + "timestamp": hexutil.Uint64(parentBlock.Time() + 12), + "prevRandao": common.HexToHash("0x" + strings.Repeat("11", 32)).Hex(), + "suggestedFeeRecipient": common.Address{}.Hex(), + "withdrawals": []interface{}{}, + } + if t.chain.Config().IsCancun(parentBlock.Number(), parentBlock.Time()) { + beaconRoot := common.HexToHash("0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884365149a42212e8822") + attrs["parentBeaconBlockRoot"] = beaconRoot.Hex() + } + _ = salt + return attrs +} + +// liveHead fetches the current canonical head from the node. It must be used instead +// of t.chain.Head() once the chain has been advanced by a prior testing_commitBlockV1 +// call, since t.chain reflects only the static pre-loaded chain.rlp. +func liveHead(ctx context.Context, t *T) (*types.Block, error) { + return t.eth.BlockByNumber(ctx, nil) +} + +// TestingCommitBlockV1 stores a list of all tests against the method. +// +// Notes on ordering: +// - These tests mutate the canonical head, so this MethodTests entry must come +// after every read-only test that assumes the static chain head. +// - Subtest names are chosen so that lexical order (used by hive's filepath.Walk) +// matches the order in which they are registered here. +// - The "from-mempool" subtest is renamed with a "z-" prefix so it runs last: +// it is SpecOnly (mempool ordering is not strictly deterministic), and putting +// it earlier in the alphabetical order would cascade non-determinism into the +// subsequent strict-match tests that take its committed block as their parent. +var TestingCommitBlockV1 = MethodTests{ + "testing_commitBlockV1", + []Test{ + { + Name: "commit-block-empty-transactions", + About: "commits an empty block using testing_commitBlockV1 and advances the canonical head", + Run: func(ctx context.Context, t *T) error { + parentBlock, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read live head: %w", err) + } + parentHash := parentBlock.Hash() + payloadAttrs := commitBlockV1PayloadAttrs(t, parentBlock, "empty") + + var result common.Hash + err = t.rpc.CallContext(ctx, &result, "testing_commitBlockV1", + payloadAttrs, + []string{}, + hexutil.Encode([]byte{}), + ) + if err != nil { + return fmt.Errorf("testing_commitBlockV1 call failed: %w", err) + } + + newHead, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read head after commit: %w", err) + } + if newHead.Hash() != result { + return fmt.Errorf("returned hash %s is not the new head %s", result.Hex(), newHead.Hash().Hex()) + } + if newHead.ParentHash() != parentHash { + return fmt.Errorf("new head parent %s does not match prior head %s", newHead.ParentHash().Hex(), parentHash.Hex()) + } + if newHead.NumberU64() != parentBlock.NumberU64()+1 { + return fmt.Errorf("new head number %d, want %d", newHead.NumberU64(), parentBlock.NumberU64()+1) + } + if len(newHead.Transactions()) != 0 { + return fmt.Errorf("expected empty block, got %d transactions", len(newHead.Transactions())) + } + return nil + }, + }, + { + Name: "commit-block-invalid-transaction", + About: "calls testing_commitBlockV1 with an unapplicable transaction (wrong nonce); client MUST return an error and not modify the canonical head", + Run: func(ctx context.Context, t *T) error { + parentBlock, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read live head: %w", err) + } + parentHash := parentBlock.Hash() + payloadAttrs := commitBlockV1PayloadAttrs(t, parentBlock, "invalid") + + sender, _ := t.chain.GetSender(2) + basefee := parentBlock.BaseFee() + if basefee == nil { + basefee = big.NewInt(1000000000) + } + gasFeeCap := new(big.Int).Add(basefee, big.NewInt(500)) + txdata := &types.DynamicFeeTx{ + Nonce: 999, // invalid: account will not have this nonce + To: &emitContract, + Gas: 21000, + GasTipCap: big.NewInt(500), + GasFeeCap: gasFeeCap, + Value: big.NewInt(1000), + } + tx := t.chain.MustSignTx(sender, txdata) + txBytes, err := tx.MarshalBinary() + if err != nil { + return fmt.Errorf("failed to marshal transaction: %w", err) + } + + var result common.Hash + err = t.rpc.CallContext(ctx, &result, "testing_commitBlockV1", + payloadAttrs, + []string{hexutil.Encode(txBytes)}, + hexutil.Encode([]byte{}), + ) + if err == nil { + return fmt.Errorf("testing_commitBlockV1 must fail when a transaction cannot be applied (e.g. invalid nonce), but it succeeded") + } + + var rpcErr rpc.Error + if !errors.As(err, &rpcErr) { + return fmt.Errorf("testing_commitBlockV1 must return an RPC error with a code, got: %w", err) + } + code := rpcErr.ErrorCode() + if code != -32602 && code != -32603 && code != -32000 { + return fmt.Errorf("testing_commitBlockV1 must return error code -32602, -32603, or -32000 for unapplicable tx, got code %d: %w", code, err) + } + + headBlock, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read head after failed commit: %w", err) + } + if headBlock.Hash() != parentHash { + return fmt.Errorf("canonical head must not change when testing_commitBlockV1 fails; was %s, now %s", parentHash.Hex(), headBlock.Hash().Hex()) + } + return nil + }, + }, + { + Name: "commit-block-with-extra-data", + About: "commits a block with a non-empty extraData value using testing_commitBlockV1", + Run: func(ctx context.Context, t *T) error { + parentBlock, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read live head: %w", err) + } + payloadAttrs := commitBlockV1PayloadAttrs(t, parentBlock, "extra") + extra := []byte("execution-apis") + extraHex := hexutil.Encode(extra) + + var result common.Hash + err = t.rpc.CallContext(ctx, &result, "testing_commitBlockV1", + payloadAttrs, + []string{}, + extraHex, + ) + if err != nil { + return fmt.Errorf("testing_commitBlockV1 call failed: %w", err) + } + newBlock, err := t.eth.BlockByHash(ctx, result) + if err != nil { + return fmt.Errorf("failed to fetch committed block: %w", err) + } + if !bytes.Equal(newBlock.Extra(), extra) { + return fmt.Errorf("extraData mismatch: got %s, want %s", hexutil.Encode(newBlock.Extra()), extraHex) + } + return nil + }, + }, + { + Name: "commit-block-with-transactions", + About: "commits a block with the specified transactions using testing_commitBlockV1 and advances the canonical head", + Run: func(ctx context.Context, t *T) error { + parentBlock, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read live head: %w", err) + } + parentHash := parentBlock.Hash() + + payloadAttrs := commitBlockV1PayloadAttrs(t, parentBlock, "with-tx") + + // Use sender index 2 to avoid conflicting with eth_sendRawTransaction tests. + sender, nonce := t.chain.GetSender(2) + basefee := parentBlock.BaseFee() + if basefee == nil { + basefee = big.NewInt(1000000000) + } + gasFeeCap := new(big.Int).Add(basefee, big.NewInt(500)) + + txdata := &types.DynamicFeeTx{ + Nonce: nonce, + To: &emitContract, + Gas: 21000, + GasTipCap: big.NewInt(500), + GasFeeCap: gasFeeCap, + Value: big.NewInt(1000), + } + tx := t.chain.MustSignTx(sender, txdata) + txBytes, err := tx.MarshalBinary() + if err != nil { + return fmt.Errorf("failed to marshal transaction: %w", err) + } + txHex := hexutil.Encode(txBytes) + + extraData := hexutil.Encode([]byte("test_name")) + + var result common.Hash + err = t.rpc.CallContext(ctx, &result, "testing_commitBlockV1", + payloadAttrs, + []string{txHex}, + extraData, + ) + if err != nil { + return fmt.Errorf("testing_commitBlockV1 call failed: %w", err) + } + if result == (common.Hash{}) { + return fmt.Errorf("testing_commitBlockV1 returned zero hash") + } + + // The returned hash MUST be the new canonical head. + newHead, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read head after commit: %w", err) + } + if newHead.Hash() != result { + return fmt.Errorf("returned hash %s is not the new head %s", result.Hex(), newHead.Hash().Hex()) + } + if newHead.ParentHash() != parentHash { + return fmt.Errorf("new head parent %s does not match prior head %s", newHead.ParentHash().Hex(), parentHash.Hex()) + } + if newHead.NumberU64() != parentBlock.NumberU64()+1 { + return fmt.Errorf("new head number %d, want %d", newHead.NumberU64(), parentBlock.NumberU64()+1) + } + + // The committed block MUST include exactly the supplied transaction. + newBlock, err := t.eth.BlockByHash(ctx, result) + if err != nil { + return fmt.Errorf("failed to fetch committed block: %w", err) + } + txs := newBlock.Transactions() + if len(txs) != 1 { + return fmt.Errorf("expected 1 transaction in committed block, got %d", len(txs)) + } + if txs[0].Hash() != tx.Hash() { + return fmt.Errorf("committed transaction hash mismatch: got %s, want %s", txs[0].Hash().Hex(), tx.Hash().Hex()) + } + + // The committed block MUST carry the supplied extraData. + wantExtra := []byte("test_name") + if !bytes.Equal(newBlock.Extra(), wantExtra) { + return fmt.Errorf("extraData mismatch: got %s, want %s", hexutil.Encode(newBlock.Extra()), hexutil.Encode(wantExtra)) + } + return nil + }, + }, + { + Name: "commit-block-z-from-mempool", + About: "commits a block built from the mempool using testing_commitBlockV1 with null transactions parameter", + SpecOnly: true, + Run: func(ctx context.Context, t *T) error { + parentBlock, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read live head: %w", err) + } + parentHash := parentBlock.Hash() + payloadAttrs := commitBlockV1PayloadAttrs(t, parentBlock, "mempool") + + // Use sender index 4 to avoid the address that testing_buildBlockV1's + // from-mempool test (sender 1) has already pushed a nonce-0 tx into the + // mempool with — that prior tx is still pending here. + sender, nonce := t.chain.GetSender(4) + basefee := parentBlock.BaseFee() + if basefee == nil { + basefee = big.NewInt(1000000000) + } + gasFeeCap := new(big.Int).Add(basefee, big.NewInt(500)) + txdata := &types.DynamicFeeTx{ + Nonce: nonce, + To: &emitContract, + Gas: 21000, + GasTipCap: big.NewInt(500), + GasFeeCap: gasFeeCap, + Value: big.NewInt(1000), + } + tx := t.chain.MustSignTx(sender, txdata) + txBytes, err := tx.MarshalBinary() + if err != nil { + return fmt.Errorf("failed to marshal transaction: %w", err) + } + var sentHash common.Hash + if err := t.rpc.CallContext(ctx, &sentHash, "eth_sendRawTransaction", hexutil.Encode(txBytes)); err != nil { + return fmt.Errorf("failed to send transaction to mempool: %w", err) + } + + var result common.Hash + err = t.rpc.CallContext(ctx, &result, "testing_commitBlockV1", + payloadAttrs, + nil, + hexutil.Encode([]byte{}), + ) + if err != nil { + return fmt.Errorf("testing_commitBlockV1 call failed: %w", err) + } + + newHead, err := liveHead(ctx, t) + if err != nil { + return fmt.Errorf("failed to read head after commit: %w", err) + } + if newHead.Hash() != result { + return fmt.Errorf("returned hash %s is not the new head %s", result.Hex(), newHead.Hash().Hex()) + } + if newHead.ParentHash() != parentHash { + return fmt.Errorf("new head parent %s does not match prior head %s", newHead.ParentHash().Hex(), parentHash.Hex()) + } + return nil + }, + }, + }, +} + var EthSimulateV1 = MethodTests{ "eth_simulateV1", []Test{ diff --git a/wordlist.txt b/wordlist.txt index 4204b9706..b9d889a90 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -11,6 +11,7 @@ blockAccessList BlockAccessList bodiesbyhashv buildBlockV +commitBlockV bodiesbyrangev bodyv bytecode