mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-08 20:47:59 -05:00
EIP-7251 add consolidation request type (#7266)
* add request type for consolidations, encoder, decoder and tests * added raw tx for consolidation * add consolidation reqs to EngineGetPayloadResultV4 * set storage slot value to 0 initially and value for tx * updates plugin api Signed-off-by: Justin Florentine <justin+github@florentine.us> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> Signed-off-by: Justin Florentine <justin+github@florentine.us> Co-authored-by: Justin Florentine <justin+github@florentine.us>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"request": {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_getBlockByNumber",
|
||||
"params": [
|
||||
"0x00", true
|
||||
],
|
||||
"id": 67
|
||||
},
|
||||
"response": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": 67,
|
||||
"result": {
|
||||
"number": "0x0",
|
||||
"hash" : "0x38d7daa68e8bac41a0a237b7cbfcef480cb9bd9adc7b282d7b0d23ff4eb8d6e5",
|
||||
"mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"nonce" : "0x0000000000000042",
|
||||
"sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "0x3ed8435adb5f3526144e6babdd3fc8c661a86097cf7e743441b41fda096fc4dd",
|
||||
"receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"miner" : "0x0000000000000000000000000000000000000000",
|
||||
"difficulty" : "0x400000000",
|
||||
"totalDifficulty" : "0x400000000",
|
||||
"extraData" : "0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"baseFeePerGas" : "0x7",
|
||||
"size" : "0x2ba",
|
||||
"gasLimit" : "0x1c9c380",
|
||||
"gasUsed" : "0x0",
|
||||
"timestamp" : "0x0",
|
||||
"uncles" : [ ],
|
||||
"transactions" : [ ],
|
||||
"withdrawalsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"withdrawals" : [ ],
|
||||
"blobGasUsed" : "0x0",
|
||||
"excessBlobGas" : "0x0",
|
||||
"parentBeaconBlockRoot" : "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -4,8 +4,8 @@
|
||||
"method": "engine_forkchoiceUpdatedV3",
|
||||
"params": [
|
||||
{
|
||||
"headBlockHash": "0x3ca89f1d6b71aeb56389ac8270e9ae369d0bb8edeea747f2d868a5eb31892b04",
|
||||
"safeBlockHash": "0x3ca89f1d6b71aeb56389ac8270e9ae369d0bb8edeea747f2d868a5eb31892b04",
|
||||
"headBlockHash": "0x38d7daa68e8bac41a0a237b7cbfcef480cb9bd9adc7b282d7b0d23ff4eb8d6e5",
|
||||
"safeBlockHash": "0x38d7daa68e8bac41a0a237b7cbfcef480cb9bd9adc7b282d7b0d23ff4eb8d6e5",
|
||||
"finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
@@ -24,10 +24,10 @@
|
||||
"result": {
|
||||
"payloadStatus": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x3ca89f1d6b71aeb56389ac8270e9ae369d0bb8edeea747f2d868a5eb31892b04",
|
||||
"latestValidHash": "0x38d7daa68e8bac41a0a237b7cbfcef480cb9bd9adc7b282d7b0d23ff4eb8d6e5",
|
||||
"validationError": null
|
||||
},
|
||||
"payloadId": "0x282643d318bdab11"
|
||||
"payloadId": "0x28264396eca1deef"
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"jsonrpc": "2.0",
|
||||
"method": "engine_getPayloadV3",
|
||||
"params": [
|
||||
"0x282643d318bdab11"
|
||||
"0x28264396eca1deef"
|
||||
],
|
||||
"id": 67
|
||||
},
|
||||
@@ -12,9 +12,9 @@
|
||||
"id": 67,
|
||||
"result": {
|
||||
"executionPayload": {
|
||||
"parentHash": "0x3ca89f1d6b71aeb56389ac8270e9ae369d0bb8edeea747f2d868a5eb31892b04",
|
||||
"parentHash": "0x38d7daa68e8bac41a0a237b7cbfcef480cb9bd9adc7b282d7b0d23ff4eb8d6e5",
|
||||
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"stateRoot": "0x2b6a1166ce24fe0af741c7313e6049e9e19351742bfaf4179154bc594ca9eb90",
|
||||
"stateRoot": "0x3ed8435adb5f3526144e6babdd3fc8c661a86097cf7e743441b41fda096fc4dd",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1c9c380",
|
||||
@@ -29,7 +29,7 @@
|
||||
"blockNumber": "0x1",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"blobGasUsed": "0x0",
|
||||
"blockHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950"
|
||||
"blockHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593"
|
||||
},
|
||||
"blockValue": "0x0",
|
||||
"blobsBundle": {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"method": "engine_newPayloadV3",
|
||||
"params": [
|
||||
{
|
||||
"parentHash": "0x3ca89f1d6b71aeb56389ac8270e9ae369d0bb8edeea747f2d868a5eb31892b04",
|
||||
"parentHash": "0x38d7daa68e8bac41a0a237b7cbfcef480cb9bd9adc7b282d7b0d23ff4eb8d6e5",
|
||||
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"stateRoot": "0x2b6a1166ce24fe0af741c7313e6049e9e19351742bfaf4179154bc594ca9eb90",
|
||||
"stateRoot": "0x3ed8435adb5f3526144e6babdd3fc8c661a86097cf7e743441b41fda096fc4dd",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1c9c380",
|
||||
@@ -17,7 +17,7 @@
|
||||
"transactions": [],
|
||||
"withdrawals": [],
|
||||
"blockNumber": "0x1",
|
||||
"blockHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"blockHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"excessBlobGas": "0x0",
|
||||
"blobGasUsed": "0x0"
|
||||
@@ -32,7 +32,7 @@
|
||||
"id": 67,
|
||||
"result": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"latestValidHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"validationError": null
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"method": "engine_forkchoiceUpdatedV3",
|
||||
"params": [
|
||||
{
|
||||
"headBlockHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"safeBlockHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"finalizedBlockHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950"
|
||||
"headBlockHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"safeBlockHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"finalizedBlockHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593"
|
||||
},
|
||||
null
|
||||
],
|
||||
@@ -18,7 +18,7 @@
|
||||
"result": {
|
||||
"payloadStatus": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"latestValidHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"validationError": null
|
||||
},
|
||||
"payloadId": null
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"method": "engine_forkchoiceUpdatedV3",
|
||||
"params": [
|
||||
{
|
||||
"headBlockHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"safeBlockHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"finalizedBlockHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950"
|
||||
"headBlockHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"safeBlockHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"finalizedBlockHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593"
|
||||
},
|
||||
{
|
||||
"timestamp": "0x20",
|
||||
@@ -24,10 +24,10 @@
|
||||
"result": {
|
||||
"payloadStatus": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"latestValidHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"validationError": null
|
||||
},
|
||||
"payloadId": "0x282643c6d89e12df"
|
||||
"payloadId": "0x282643d3a905e721"
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"jsonrpc": "2.0",
|
||||
"method": "engine_getPayloadV4",
|
||||
"params": [
|
||||
"0x282643c6d89e12df"
|
||||
"0x282643d3a905e721"
|
||||
],
|
||||
"id": 67
|
||||
},
|
||||
@@ -12,9 +12,9 @@
|
||||
"id": 67,
|
||||
"result": {
|
||||
"executionPayload": {
|
||||
"parentHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"parentHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"stateRoot": "0x546ac65b9d37c72d7185f8dd67419803c636dd4e5ddf9b325fb64e9ecf570871",
|
||||
"stateRoot": "0x2e59916a57b535875bcd80d8472aeaa0027aa685d159804e8caa2f12d060155e",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1c9c380",
|
||||
@@ -34,8 +34,9 @@
|
||||
"amount": "0x0"
|
||||
}
|
||||
],
|
||||
"consolidationRequests" : [],
|
||||
"blockNumber": "0x2",
|
||||
"blockHash": "0xa7a92cc82e1d876476ad6433538599b0d592f88ba0823c23e80af93fb1748f14",
|
||||
"blockHash": "0x27a2bc2ac21b3fc796f636bec1ec9cba100435f9a793176a83a5d4fa7cc13006",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"blobGasUsed": "0x0"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"method": "engine_newPayloadV4",
|
||||
"params": [
|
||||
{
|
||||
"parentHash": "0xa7a92cc82e1d876476ad6433538599b0d592f88ba0823c23e80af93fb1748f14",
|
||||
"parentHash": "0x27a2bc2ac21b3fc796f636bec1ec9cba100435f9a793176a83a5d4fa7cc13006",
|
||||
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"stateRoot": "0x9b8c4a9a86cb49252075c0db2f0e72fb1e49350a0f70ea36f26f700201961e62",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"method": "engine_newPayloadV4",
|
||||
"params": [
|
||||
{
|
||||
"parentHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
|
||||
"parentHash": "0x8082deff44f79489ea92415be59afb48b6f46b939553f855479828a6f87f9593",
|
||||
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"stateRoot": "0xdb2a9bb9097dd6946525203a14437cd925ef549289e1fe17c6ed845c53647a26",
|
||||
"stateRoot": "0x961878fdcdff52ea42db0026f59aa414a5ec2835e56ed1a8ae50c80a9fe3a04b",
|
||||
"logsBloom": "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000",
|
||||
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1c9c380",
|
||||
@@ -35,8 +35,9 @@
|
||||
"validatorPubkey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"
|
||||
}
|
||||
],
|
||||
"consolidationRequests": [],
|
||||
"blockNumber": "0x2",
|
||||
"blockHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
|
||||
"blockHash": "0xc67a660f5d3c20ee603911bdff1e409e976f306883dff8ef4999dca3176f7dca",
|
||||
"receiptsRoot": "0x79ee3424eb720a3ad4b1c5a372bb8160580cbe4d893778660f34213c685627a9",
|
||||
"blobGasUsed": "0x0"
|
||||
},
|
||||
@@ -50,7 +51,7 @@
|
||||
"id": 67,
|
||||
"result": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
|
||||
"latestValidHash": "0xc67a660f5d3c20ee603911bdff1e409e976f306883dff8ef4999dca3176f7dca",
|
||||
"validationError": null
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"method": "engine_forkchoiceUpdatedV3",
|
||||
"params": [
|
||||
{
|
||||
"headBlockHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
|
||||
"safeBlockHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
|
||||
"finalizedBlockHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d"
|
||||
"headBlockHash": "0xc67a660f5d3c20ee603911bdff1e409e976f306883dff8ef4999dca3176f7dca",
|
||||
"safeBlockHash": "0xc67a660f5d3c20ee603911bdff1e409e976f306883dff8ef4999dca3176f7dca",
|
||||
"finalizedBlockHash": "0xc67a660f5d3c20ee603911bdff1e409e976f306883dff8ef4999dca3176f7dca"
|
||||
},
|
||||
{
|
||||
"timestamp": "0x30",
|
||||
@@ -24,10 +24,10 @@
|
||||
"result": {
|
||||
"payloadStatus": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
|
||||
"latestValidHash": "0xc67a660f5d3c20ee603911bdff1e409e976f306883dff8ef4999dca3176f7dca",
|
||||
"validationError": null
|
||||
},
|
||||
"payloadId": "0x282643e2da21a7cf"
|
||||
"payloadId": "0x282643a16a58b5cf"
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"jsonrpc": "2.0",
|
||||
"method": "engine_getPayloadV4",
|
||||
"params": [
|
||||
"0x282643e2da21a7cf"
|
||||
"0x282643a16a58b5cf"
|
||||
],
|
||||
"id": 67
|
||||
},
|
||||
@@ -12,9 +12,9 @@
|
||||
"id": 67,
|
||||
"result": {
|
||||
"executionPayload": {
|
||||
"parentHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
|
||||
"parentHash": "0xc67a660f5d3c20ee603911bdff1e409e976f306883dff8ef4999dca3176f7dca",
|
||||
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"stateRoot": "0xcd9f15de5f17cf87a02bf795a0dc98c108eead4651eca57fc7195bda0d9c20ee",
|
||||
"stateRoot": "0x5fc31c01a451fe02f0e938de7ec7044aaba1159a81a1be64357bc70af226f304",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1c9c380",
|
||||
@@ -28,8 +28,9 @@
|
||||
"withdrawals": [],
|
||||
"depositRequests": [],
|
||||
"withdrawalRequests": [],
|
||||
"consolidationRequests" : [],
|
||||
"blockNumber": "0x3",
|
||||
"blockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
|
||||
"blockHash": "0xdbb55a049f14b8152695bf3bbd754aa1fd55bbe10b306eb49caa4bd7d7fcb634",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"blobGasUsed": "0x0"
|
||||
},
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"method": "engine_newPayloadV3",
|
||||
"params": [
|
||||
{
|
||||
"parentHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
|
||||
"parentHash": "0xc67a660f5d3c20ee603911bdff1e409e976f306883dff8ef4999dca3176f7dca",
|
||||
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"stateRoot": "0xcd9f15de5f17cf87a02bf795a0dc98c108eead4651eca57fc7195bda0d9c20ee",
|
||||
"stateRoot": "0x5fc31c01a451fe02f0e938de7ec7044aaba1159a81a1be64357bc70af226f304",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1c9c380",
|
||||
@@ -19,7 +19,7 @@
|
||||
"depositRequests": [],
|
||||
"withdrawalRequests": [],
|
||||
"blockNumber": "0x3",
|
||||
"blockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
|
||||
"blockHash": "0xdbb55a049f14b8152695bf3bbd754aa1fd55bbe10b306eb49caa4bd7d7fcb634",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"excessBlobGas": "0x0",
|
||||
"blobGasUsed": "0x0"
|
||||
@@ -34,7 +34,7 @@
|
||||
"id": 67,
|
||||
"result": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
|
||||
"latestValidHash": "0xdbb55a049f14b8152695bf3bbd754aa1fd55bbe10b306eb49caa4bd7d7fcb634",
|
||||
"validationError": null
|
||||
}
|
||||
},
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"request": {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_sendRawTransaction",
|
||||
"params": ["0xf8c80185e8d4a51000832dc6c09400b42dbf2194e931e80326d950320f7d9dbeac0201b860fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe822fe0a05b88b593926d340f448918ef1c6263356c37f2434774e0fdb1cb9d90cfa5a23ba003a86aac4adb774181ba51eda17efb5fbed99ad57895e6eb56ccdf508a88a7cc"],
|
||||
"id": 67
|
||||
},
|
||||
"response": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": 67,
|
||||
"result": "0xa4252f576c4e16cb020f86f8a30d4fa990ee0cbfc84198a6d0eb118dd2f8b72d"
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
"method": "engine_forkchoiceUpdatedV3",
|
||||
"params": [
|
||||
{
|
||||
"headBlockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
|
||||
"safeBlockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
|
||||
"finalizedBlockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42"
|
||||
"headBlockHash": "0xdbb55a049f14b8152695bf3bbd754aa1fd55bbe10b306eb49caa4bd7d7fcb634",
|
||||
"safeBlockHash": "0xdbb55a049f14b8152695bf3bbd754aa1fd55bbe10b306eb49caa4bd7d7fcb634",
|
||||
"finalizedBlockHash": "0xdbb55a049f14b8152695bf3bbd754aa1fd55bbe10b306eb49caa4bd7d7fcb634"
|
||||
},
|
||||
{
|
||||
"timestamp": "0x40",
|
||||
@@ -24,10 +24,10 @@
|
||||
"result": {
|
||||
"payloadStatus": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
|
||||
"latestValidHash": "0xdbb55a049f14b8152695bf3bbd754aa1fd55bbe10b306eb49caa4bd7d7fcb634",
|
||||
"validationError": null
|
||||
},
|
||||
"payloadId": "0x282643de0e3d43bf"
|
||||
"payloadId": "0x28264396a9634d41"
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
@@ -3,7 +3,7 @@
|
||||
"jsonrpc": "2.0",
|
||||
"method": "engine_getPayloadV4",
|
||||
"params": [
|
||||
"0x282643de0e3d43bf"
|
||||
"0x28264396a9634d41"
|
||||
],
|
||||
"id": 67
|
||||
},
|
||||
@@ -12,20 +12,21 @@
|
||||
"id": 67,
|
||||
"result": {
|
||||
"executionPayload": {
|
||||
"parentHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
|
||||
"parentHash": "0xdbb55a049f14b8152695bf3bbd754aa1fd55bbe10b306eb49caa4bd7d7fcb634",
|
||||
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"stateRoot": "0xe4642cc58d61f2392fe056042c226e286f22a25e3104f4a4acb423dad9a43311",
|
||||
"stateRoot": "0x49df1f1a1d28a23fa752230d442077768787d392e9edb70c83d727d31e55eaac",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1c9c380",
|
||||
"gasUsed": "0x145d3",
|
||||
"gasUsed": "0x3ad4d",
|
||||
"timestamp": "0x40",
|
||||
"extraData": "0x",
|
||||
"baseFeePerGas": "0x7",
|
||||
"excessBlobGas": "0x0",
|
||||
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"transactions": [
|
||||
"0xf8a08085e8d4a51000832dc6c09400a3ca265ebcb825b45f985a16cefb49958ce01702b8388706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf2430000000000000000822fdfa00476c1a81f80f4c130acb5f8b8075468ba0893d766b7ec51a8d9723c573ad034a03bd3eaedabbaaf745f15023185ba66584ad3ee8bb40b9bef8c0b9ed27f8b1959"
|
||||
"0xf8a08085e8d4a51000832dc6c09400a3ca265ebcb825b45f985a16cefb49958ce01702b8388706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf2430000000000000000822fdfa00476c1a81f80f4c130acb5f8b8075468ba0893d766b7ec51a8d9723c573ad034a03bd3eaedabbaaf745f15023185ba66584ad3ee8bb40b9bef8c0b9ed27f8b1959",
|
||||
"0xf8c80185e8d4a51000832dc6c09400b42dbf2194e931e80326d950320f7d9dbeac0201b860fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe822fe0a05b88b593926d340f448918ef1c6263356c37f2434774e0fdb1cb9d90cfa5a23ba003a86aac4adb774181ba51eda17efb5fbed99ad57895e6eb56ccdf508a88a7cc"
|
||||
],
|
||||
"withdrawals": [],
|
||||
"depositRequests": [],
|
||||
@@ -36,12 +37,19 @@
|
||||
"validatorPubkey": "0x8706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243"
|
||||
}
|
||||
],
|
||||
"consolidationRequests": [
|
||||
{
|
||||
"sourceAddress": "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f",
|
||||
"sourcePubKey": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"targetPubKey": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
|
||||
}
|
||||
],
|
||||
"blockNumber": "0x4",
|
||||
"receiptsRoot": "0x765bd9d63cc10fa47117d6cc0958f15e55a3bde540d4ed15d220f573fbb82cba",
|
||||
"receiptsRoot": "0x970fc81bb3e7fb21435f9a65a184aa9e3fd2f52b89fd859302b46954354266b5",
|
||||
"blobGasUsed": "0x0",
|
||||
"blockHash": "0xb2d60adb2a0c73313ebdacf425b1d6bbd810c3ec6b28ad0d62a73cdc34cb696a"
|
||||
"blockHash": "0x93df6f3484202f24c692354e2ab96e9948ae45eea6ad85faea121a389e468ea8"
|
||||
},
|
||||
"blockValue": "0x12855dcd153473b",
|
||||
"blockValue": "0x3581baab15c12e5",
|
||||
"blobsBundle": {
|
||||
"commitments": [],
|
||||
"proofs": [],
|
||||
@@ -19,7 +19,9 @@ public enum RequestType {
|
||||
/** DEPOSITS */
|
||||
DEPOSIT(0x00),
|
||||
/** WITHDRAWAL */
|
||||
WITHDRAWAL(0x01);
|
||||
WITHDRAWAL(0x01),
|
||||
/** CONSOLIDATION */
|
||||
CONSOLIDATION(0x02);
|
||||
|
||||
private final int typeValue;
|
||||
|
||||
@@ -48,6 +50,7 @@ public enum RequestType {
|
||||
return switch (serializedTypeValue) {
|
||||
case 0x00 -> DEPOSIT;
|
||||
case 0x01 -> WITHDRAWAL;
|
||||
case 0x02 -> CONSOLIDATION;
|
||||
default ->
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Unsupported request type: 0x%02X", serializedTypeValue));
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.Executi
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID_BLOCK_HASH;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.SYNCING;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.VALID;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.RequestValidatorProvider.getConsolidationRequestValidator;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.RequestValidatorProvider.getDepositRequestValidator;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.RequestValidatorProvider.getWithdrawalRequestValidator;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.WithdrawalsValidatorProvider.getWithdrawalsValidator;
|
||||
@@ -35,6 +36,7 @@ import org.hyperledger.besu.ethereum.BlockProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.ConsolidationRequestParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositRequestParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter;
|
||||
@@ -185,8 +187,23 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
|
||||
reqId, new JsonRpcError(INVALID_PARAMS, "Invalid withdrawal request"));
|
||||
}
|
||||
|
||||
final Optional<List<Request>> maybeConsolidationRequests =
|
||||
Optional.ofNullable(blockParam.getConsolidationRequests())
|
||||
.map(
|
||||
consolidationRequest ->
|
||||
consolidationRequest.stream()
|
||||
.map(ConsolidationRequestParameter::toConsolidationRequest)
|
||||
.collect(toList()));
|
||||
if (!getConsolidationRequestValidator(
|
||||
protocolSchedule.get(), blockParam.getTimestamp(), blockParam.getBlockNumber())
|
||||
.validateParameter(maybeConsolidationRequests)) {
|
||||
return new JsonRpcErrorResponse(
|
||||
reqId, new JsonRpcError(INVALID_PARAMS, "Invalid consolidation request"));
|
||||
}
|
||||
|
||||
Optional<List<Request>> maybeRequests =
|
||||
RequestUtil.combine(maybeDepositRequests, maybeWithdrawalRequests);
|
||||
RequestUtil.combine(
|
||||
maybeDepositRequests, maybeWithdrawalRequests, maybeConsolidationRequests);
|
||||
|
||||
if (mergeContext.get().isSyncing()) {
|
||||
LOG.debug("We are syncing");
|
||||
|
||||
@@ -38,6 +38,12 @@ public class RequestValidatorProvider {
|
||||
protocolSchedule, blockTimestamp, blockNumber, RequestType.WITHDRAWAL);
|
||||
}
|
||||
|
||||
public static RequestValidator getConsolidationRequestValidator(
|
||||
final ProtocolSchedule protocolSchedule, final long blockTimestamp, final long blockNumber) {
|
||||
return getRequestValidator(
|
||||
protocolSchedule, blockTimestamp, blockNumber, RequestType.CONSOLIDATION);
|
||||
}
|
||||
|
||||
private static RequestValidator getRequestValidator(
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final long blockTimestamp,
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BLSPublicKey;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class ConsolidationRequestParameter {
|
||||
|
||||
private final String sourceAddress;
|
||||
private final String sourcePubkey;
|
||||
private final String targetPubkey;
|
||||
|
||||
@JsonCreator
|
||||
public ConsolidationRequestParameter(
|
||||
@JsonProperty("sourceAddress") final String sourceAddress,
|
||||
@JsonProperty("sourcePubkey") final String sourcePubkey,
|
||||
@JsonProperty("targetPubkey") final String targetPubkey) {
|
||||
this.sourceAddress = sourceAddress;
|
||||
this.sourcePubkey = sourcePubkey;
|
||||
this.targetPubkey = targetPubkey;
|
||||
}
|
||||
|
||||
public static ConsolidationRequestParameter fromConsolidationRequest(
|
||||
final ConsolidationRequest consolidationRequest) {
|
||||
return new ConsolidationRequestParameter(
|
||||
consolidationRequest.getSourceAddress().toHexString(),
|
||||
consolidationRequest.getSourcePubkey().toHexString(),
|
||||
consolidationRequest.getTargetPubkey().toHexString());
|
||||
}
|
||||
|
||||
public ConsolidationRequest toConsolidationRequest() {
|
||||
return new ConsolidationRequest(
|
||||
Address.fromHexString(sourceAddress),
|
||||
BLSPublicKey.fromHexString(sourcePubkey),
|
||||
BLSPublicKey.fromHexString(targetPubkey));
|
||||
}
|
||||
|
||||
@JsonGetter
|
||||
public String getSourceAddress() {
|
||||
return sourceAddress;
|
||||
}
|
||||
|
||||
@JsonGetter
|
||||
public String getSourcePubKey() {
|
||||
return sourcePubkey;
|
||||
}
|
||||
|
||||
@JsonGetter
|
||||
public String getTargetPubKey() {
|
||||
return targetPubkey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final ConsolidationRequestParameter that = (ConsolidationRequestParameter) o;
|
||||
return Objects.equals(sourceAddress, that.sourceAddress)
|
||||
&& Objects.equals(sourcePubkey, that.sourcePubkey)
|
||||
&& Objects.equals(targetPubkey, that.targetPubkey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(sourceAddress, sourcePubkey, targetPubkey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConsolidationRequestParameter{"
|
||||
+ "sourceAddress='"
|
||||
+ sourceAddress
|
||||
+ '\''
|
||||
+ ", sourcePubkey='"
|
||||
+ sourcePubkey
|
||||
+ '\''
|
||||
+ ", targetPubkey='"
|
||||
+ targetPubkey
|
||||
+ '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ public class EnginePayloadParameter {
|
||||
private final String excessBlobGas;
|
||||
private final List<DepositRequestParameter> depositRequests;
|
||||
private final List<WithdrawalRequestParameter> withdrawalRequests;
|
||||
private final List<ConsolidationRequestParameter> consolidationRequests;
|
||||
|
||||
/**
|
||||
* Creates an instance of EnginePayloadParameter.
|
||||
@@ -68,6 +69,7 @@ public class EnginePayloadParameter {
|
||||
* @param excessBlobGas QUANTITY, 64 Bits
|
||||
* @param depositRequests List of deposit parameters.
|
||||
* @param withdrawalRequestParameters List of withdrawal requests parameters.
|
||||
* @param consolidationRequests List of consolidation requests parameters.
|
||||
*/
|
||||
@JsonCreator
|
||||
public EnginePayloadParameter(
|
||||
@@ -90,7 +92,9 @@ public class EnginePayloadParameter {
|
||||
@JsonProperty("excessBlobGas") final String excessBlobGas,
|
||||
@JsonProperty("depositRequests") final List<DepositRequestParameter> depositRequests,
|
||||
@JsonProperty("withdrawalRequests")
|
||||
final List<WithdrawalRequestParameter> withdrawalRequestParameters) {
|
||||
final List<WithdrawalRequestParameter> withdrawalRequestParameters,
|
||||
@JsonProperty("consolidationRequests")
|
||||
final List<ConsolidationRequestParameter> consolidationRequests) {
|
||||
this.blockHash = blockHash;
|
||||
this.parentHash = parentHash;
|
||||
this.feeRecipient = feeRecipient;
|
||||
@@ -110,6 +114,7 @@ public class EnginePayloadParameter {
|
||||
this.excessBlobGas = excessBlobGas;
|
||||
this.depositRequests = depositRequests;
|
||||
this.withdrawalRequests = withdrawalRequestParameters;
|
||||
this.consolidationRequests = consolidationRequests;
|
||||
}
|
||||
|
||||
public Hash getBlockHash() {
|
||||
@@ -187,4 +192,8 @@ public class EnginePayloadParameter {
|
||||
public List<WithdrawalRequestParameter> getWithdrawalRequests() {
|
||||
return withdrawalRequests;
|
||||
}
|
||||
|
||||
public List<ConsolidationRequestParameter> getConsolidationRequests() {
|
||||
return consolidationRequests;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getConsolidationRequests;
|
||||
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getDepositRequests;
|
||||
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getWithdrawalRequests;
|
||||
|
||||
@@ -170,6 +171,7 @@ public class BlockResultFactory {
|
||||
blockWithReceipts.getBlock().getBody().getWithdrawals(),
|
||||
getDepositRequests(blockWithReceipts.getBlock().getBody().getRequests()),
|
||||
getWithdrawalRequests(blockWithReceipts.getBlock().getBody().getRequests()),
|
||||
getConsolidationRequests(blockWithReceipts.getBlock().getBody().getRequests()),
|
||||
Quantity.create(payload.blockValue()),
|
||||
blobsBundleV1);
|
||||
}
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
|
||||
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.ConsolidationRequestParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositRequestParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalRequestParameter;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
import org.hyperledger.besu.ethereum.core.DepositRequest;
|
||||
import org.hyperledger.besu.ethereum.core.Withdrawal;
|
||||
import org.hyperledger.besu.ethereum.core.WithdrawalRequest;
|
||||
@@ -44,10 +46,17 @@ public class EngineGetPayloadResultV4 {
|
||||
final Optional<List<Withdrawal>> withdrawals,
|
||||
final Optional<List<DepositRequest>> depositRequests,
|
||||
final Optional<List<WithdrawalRequest>> withdrawalRequests,
|
||||
final Optional<List<ConsolidationRequest>> consolidationRequests,
|
||||
final String blockValue,
|
||||
final BlobsBundleV1 blobsBundle) {
|
||||
this.executionPayload =
|
||||
new PayloadResult(header, transactions, withdrawals, depositRequests, withdrawalRequests);
|
||||
new PayloadResult(
|
||||
header,
|
||||
transactions,
|
||||
withdrawals,
|
||||
depositRequests,
|
||||
withdrawalRequests,
|
||||
consolidationRequests);
|
||||
this.blockValue = blockValue;
|
||||
this.blobsBundle = blobsBundle;
|
||||
this.shouldOverrideBuilder = false;
|
||||
@@ -96,13 +105,15 @@ public class EngineGetPayloadResultV4 {
|
||||
private final List<WithdrawalParameter> withdrawals;
|
||||
private final List<DepositRequestParameter> depositRequests;
|
||||
private final List<WithdrawalRequestParameter> withdrawalRequests;
|
||||
private final List<ConsolidationRequestParameter> consolidationRequests;
|
||||
|
||||
public PayloadResult(
|
||||
final BlockHeader header,
|
||||
final List<String> transactions,
|
||||
final Optional<List<Withdrawal>> withdrawals,
|
||||
final Optional<List<DepositRequest>> depositRequests,
|
||||
final Optional<List<WithdrawalRequest>> withdrawalRequests) {
|
||||
final Optional<List<WithdrawalRequest>> withdrawalRequests,
|
||||
final Optional<List<ConsolidationRequest>> consolidationRequests) {
|
||||
this.blockNumber = Quantity.create(header.getNumber());
|
||||
this.blockHash = header.getHash().toString();
|
||||
this.parentHash = header.getParentHash().toString();
|
||||
@@ -141,6 +152,14 @@ public class EngineGetPayloadResultV4 {
|
||||
.map(WithdrawalRequestParameter::fromWithdrawalRequest)
|
||||
.collect(Collectors.toList()))
|
||||
.orElse(null);
|
||||
this.consolidationRequests =
|
||||
consolidationRequests
|
||||
.map(
|
||||
wr ->
|
||||
wr.stream()
|
||||
.map(ConsolidationRequestParameter::fromConsolidationRequest)
|
||||
.collect(Collectors.toList()))
|
||||
.orElse(null);
|
||||
this.blobGasUsed = header.getBlobGasUsed().map(Quantity::create).orElse(Quantity.HEX_ZERO);
|
||||
this.excessBlobGas =
|
||||
header.getExcessBlobGas().map(Quantity::create).orElse(Quantity.HEX_ZERO);
|
||||
@@ -228,6 +247,11 @@ public class EngineGetPayloadResultV4 {
|
||||
return withdrawalRequests;
|
||||
}
|
||||
|
||||
@JsonGetter(value = "consolidationRequests")
|
||||
public List<ConsolidationRequestParameter> getConsolidationRequests() {
|
||||
return consolidationRequests;
|
||||
}
|
||||
|
||||
@JsonGetter(value = "feeRecipient")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public String getFeeRecipient() {
|
||||
@@ -240,7 +264,7 @@ public class EngineGetPayloadResultV4 {
|
||||
}
|
||||
|
||||
@JsonGetter(value = "blobGasUsed")
|
||||
public String getBlobGasUseds() {
|
||||
public String getBlobGasUsed() {
|
||||
return blobGasUsed;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.ConsolidationRequestParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositRequestParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter;
|
||||
@@ -403,7 +404,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
|
||||
|
||||
protected EnginePayloadParameter mockEnginePayload(
|
||||
final BlockHeader header, final List<String> txs) {
|
||||
return mockEnginePayload(header, txs, null, null, null);
|
||||
return mockEnginePayload(header, txs, null, null, null, null);
|
||||
}
|
||||
|
||||
protected EnginePayloadParameter mockEnginePayload(
|
||||
@@ -411,7 +412,8 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
|
||||
final List<String> txs,
|
||||
final List<WithdrawalParameter> withdrawals,
|
||||
final List<DepositRequestParameter> depositRequests,
|
||||
final List<WithdrawalRequestParameter> withdrawalRequests) {
|
||||
final List<WithdrawalRequestParameter> withdrawalRequests,
|
||||
final List<ConsolidationRequestParameter> consolidationRequests) {
|
||||
return new EnginePayloadParameter(
|
||||
header.getHash(),
|
||||
header.getParentHash(),
|
||||
@@ -431,7 +433,8 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
|
||||
header.getBlobGasUsed().map(UnsignedLongParameter::new).orElse(null),
|
||||
header.getExcessBlobGas().map(BlobGas::toHexString).orElse(null),
|
||||
depositRequests,
|
||||
withdrawalRequests);
|
||||
withdrawalRequests,
|
||||
consolidationRequests);
|
||||
}
|
||||
|
||||
protected BlockHeader setupValidPayload(
|
||||
|
||||
@@ -150,6 +150,7 @@ public class EngineGetPayloadV4Test extends AbstractEngineGetPayloadTest {
|
||||
assertThat(res.getExecutionPayload().getWithdrawals()).isNotNull();
|
||||
assertThat(res.getExecutionPayload().getDepositRequests()).isNotNull();
|
||||
assertThat(res.getExecutionPayload().getWithdrawalRequests()).isNotNull();
|
||||
assertThat(res.getExecutionPayload().getConsolidationRequests()).isNotNull();
|
||||
assertThat(res.getExecutionPayload().getHash())
|
||||
.isEqualTo(header.getHash().toString());
|
||||
assertThat(res.getBlockValue()).isEqualTo(Quantity.create(0));
|
||||
|
||||
@@ -87,7 +87,9 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
|
||||
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
|
||||
.thenReturn(Optional.of(mock(BlockHeader.class)));
|
||||
var resp =
|
||||
resp(mockEnginePayload(mockHeader, Collections.emptyList(), withdrawalsParam, null, null));
|
||||
resp(
|
||||
mockEnginePayload(
|
||||
mockHeader, Collections.emptyList(), withdrawalsParam, null, null, null));
|
||||
|
||||
assertValidResponse(mockHeader, resp);
|
||||
}
|
||||
@@ -107,7 +109,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
|
||||
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
|
||||
.thenReturn(Optional.of(mock(BlockHeader.class)));
|
||||
var resp =
|
||||
resp(mockEnginePayload(mockHeader, Collections.emptyList(), withdrawals, null, null));
|
||||
resp(mockEnginePayload(mockHeader, Collections.emptyList(), withdrawals, null, null, null));
|
||||
|
||||
assertValidResponse(mockHeader, resp);
|
||||
}
|
||||
@@ -127,6 +129,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
|
||||
Collections.emptyList(),
|
||||
withdrawals,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
|
||||
final JsonRpcError jsonRpcError = fromErrorResp(resp);
|
||||
@@ -143,7 +146,8 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
|
||||
.blobGasUsed(100L)
|
||||
.buildHeader();
|
||||
|
||||
var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null));
|
||||
var resp =
|
||||
resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null));
|
||||
final JsonRpcError jsonRpcError = fromErrorResp(resp);
|
||||
assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode());
|
||||
assertThat(jsonRpcError.getData()).isEqualTo("non-null BlobGasUsed pre-cancun");
|
||||
@@ -159,7 +163,8 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
|
||||
.excessBlobGas(BlobGas.MAX_BLOB_GAS)
|
||||
.buildHeader();
|
||||
|
||||
var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null));
|
||||
var resp =
|
||||
resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null));
|
||||
|
||||
final JsonRpcError jsonRpcError = fromErrorResp(resp);
|
||||
assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode());
|
||||
@@ -180,6 +185,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
|
||||
Collections.emptyList(),
|
||||
withdrawals,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
|
||||
assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode());
|
||||
|
||||
@@ -137,7 +137,7 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
|
||||
Optional.empty(),
|
||||
Optional.empty());
|
||||
final EnginePayloadParameter payload =
|
||||
mockEnginePayload(mockHeader, Collections.emptyList(), null, null, null);
|
||||
mockEnginePayload(mockHeader, Collections.emptyList(), null, null, null, null);
|
||||
|
||||
ValidationResult<RpcErrorType> res =
|
||||
method.validateParameters(
|
||||
@@ -193,7 +193,8 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
|
||||
.blobGasUsed(null)
|
||||
.buildHeader();
|
||||
|
||||
var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null));
|
||||
var resp =
|
||||
resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null));
|
||||
|
||||
final JsonRpcError jsonRpcError = fromErrorResp(resp);
|
||||
assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode());
|
||||
@@ -212,7 +213,8 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
|
||||
.blobGasUsed(100L)
|
||||
.buildHeader();
|
||||
|
||||
var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null));
|
||||
var resp =
|
||||
resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null));
|
||||
|
||||
final JsonRpcError jsonRpcError = fromErrorResp(resp);
|
||||
assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode());
|
||||
|
||||
@@ -109,7 +109,9 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
|
||||
.thenReturn(Optional.of(mockHeader.getHash()));
|
||||
|
||||
var resp =
|
||||
resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, depositRequests, null));
|
||||
resp(
|
||||
mockEnginePayload(
|
||||
mockHeader, Collections.emptyList(), null, depositRequests, null, null));
|
||||
|
||||
assertValidResponse(mockHeader, resp);
|
||||
}
|
||||
@@ -125,6 +127,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
depositRequests,
|
||||
null,
|
||||
null));
|
||||
|
||||
assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode());
|
||||
@@ -152,7 +155,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
|
||||
var resp =
|
||||
resp(
|
||||
mockEnginePayload(
|
||||
mockHeader, Collections.emptyList(), null, depositRequestsParam, null));
|
||||
mockHeader, Collections.emptyList(), null, depositRequestsParam, null, null));
|
||||
|
||||
assertValidResponse(mockHeader, resp);
|
||||
}
|
||||
@@ -172,6 +175,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
depositRequests,
|
||||
null,
|
||||
null));
|
||||
|
||||
final JsonRpcError jsonRpcError = fromErrorResp(resp);
|
||||
@@ -195,7 +199,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
|
||||
when(mergeCoordinator.getLatestValidAncestor(mockHeader))
|
||||
.thenReturn(Optional.of(mockHeader.getHash()));
|
||||
|
||||
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, null, null));
|
||||
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, null, null, null));
|
||||
|
||||
assertValidResponse(mockHeader, resp);
|
||||
}
|
||||
@@ -211,6 +215,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
|
||||
assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode());
|
||||
@@ -239,7 +244,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
|
||||
var resp =
|
||||
resp(
|
||||
mockEnginePayload(
|
||||
mockHeader, Collections.emptyList(), null, null, withdrawalRequestsParams));
|
||||
mockHeader, Collections.emptyList(), null, null, withdrawalRequestsParams, null));
|
||||
|
||||
assertValidResponse(mockHeader, resp);
|
||||
}
|
||||
@@ -258,7 +263,8 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null,
|
||||
withdrawalRequests));
|
||||
withdrawalRequests,
|
||||
null));
|
||||
|
||||
final JsonRpcError jsonRpcError = fromErrorResp(resp);
|
||||
assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode());
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.core;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BLSPublicKey;
|
||||
import org.hyperledger.besu.datatypes.PublicKey;
|
||||
import org.hyperledger.besu.datatypes.RequestType;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ConsolidationRequest extends Request
|
||||
implements org.hyperledger.besu.plugin.data.ConsolidationRequest {
|
||||
|
||||
private final Address sourceAddress;
|
||||
private final BLSPublicKey sourcePubkey;
|
||||
private final BLSPublicKey targetPubkey;
|
||||
|
||||
public ConsolidationRequest(
|
||||
final Address sourceAddress,
|
||||
final BLSPublicKey sourcePubkey,
|
||||
final BLSPublicKey targetPubkey) {
|
||||
this.sourceAddress = sourceAddress;
|
||||
this.sourcePubkey = sourcePubkey;
|
||||
this.targetPubkey = targetPubkey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestType getType() {
|
||||
return RequestType.CONSOLIDATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getSourceAddress() {
|
||||
return sourceAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublicKey getSourcePubkey() {
|
||||
return sourcePubkey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublicKey getTargetPubkey() {
|
||||
return targetPubkey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConsolidationRequest{"
|
||||
+ "sourceAddress="
|
||||
+ sourceAddress
|
||||
+ " sourcePubkey="
|
||||
+ sourcePubkey
|
||||
+ " targetPubkey="
|
||||
+ targetPubkey
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final ConsolidationRequest that = (ConsolidationRequest) o;
|
||||
return Objects.equals(sourceAddress, that.sourceAddress)
|
||||
&& Objects.equals(sourcePubkey, that.sourcePubkey)
|
||||
&& Objects.equals(targetPubkey, that.targetPubkey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(sourceAddress, sourcePubkey, targetPubkey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.core.encoding;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BLSPublicKey;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
public class ConsolidationRequestDecoder {
|
||||
|
||||
public static ConsolidationRequest decode(final RLPInput rlpInput) {
|
||||
rlpInput.enterList();
|
||||
final Address sourceAddress = Address.readFrom(rlpInput);
|
||||
final BLSPublicKey sourcePublicKey = BLSPublicKey.readFrom(rlpInput);
|
||||
final BLSPublicKey targetPublicKey = BLSPublicKey.readFrom(rlpInput);
|
||||
rlpInput.leaveList();
|
||||
|
||||
return new ConsolidationRequest(sourceAddress, sourcePublicKey, targetPublicKey);
|
||||
}
|
||||
|
||||
public static ConsolidationRequest decodeOpaqueBytes(final Bytes input) {
|
||||
return decode(RLP.input(input));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.core.encoding;
|
||||
|
||||
import org.hyperledger.besu.datatypes.RequestType;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
import org.hyperledger.besu.ethereum.core.Request;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
public class ConsolidationRequestEncoder {
|
||||
|
||||
/**
|
||||
* Encodes a Request into RLP format if it is a ConsolidationRequest.
|
||||
*
|
||||
* @param request The Request to encode, which must be a ConsolidationRequest.
|
||||
* @param rlpOutput The RLPOutput to write the encoded data to.
|
||||
* @throws IllegalArgumentException if the provided request is not a ConsolidationRequest.
|
||||
*/
|
||||
public static void encode(final Request request, final RLPOutput rlpOutput) {
|
||||
if (!request.getType().equals(RequestType.CONSOLIDATION)) {
|
||||
throw new IllegalArgumentException(
|
||||
"The provided request is not of type ConsolidationRequest.");
|
||||
}
|
||||
encodeConsolidationRequest((ConsolidationRequest) request, rlpOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the details of a ConsolidationRequest into RLP format.
|
||||
*
|
||||
* @param consolidationRequest The ConsolidationRequest to encode.
|
||||
* @param rlpOutput The RLPOutput to write the encoded data to.
|
||||
*/
|
||||
private static void encodeConsolidationRequest(
|
||||
final ConsolidationRequest consolidationRequest, final RLPOutput rlpOutput) {
|
||||
rlpOutput.startList();
|
||||
rlpOutput.writeBytes(consolidationRequest.getSourceAddress());
|
||||
rlpOutput.writeBytes(consolidationRequest.getSourcePubkey());
|
||||
rlpOutput.writeBytes(consolidationRequest.getTargetPubkey());
|
||||
rlpOutput.endList();
|
||||
}
|
||||
|
||||
public static Bytes encodeOpaqueBytes(final Request consolidationRequest) {
|
||||
return RLP.encode(rlpOutput -> encode(consolidationRequest, rlpOutput));
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,9 @@ public class RequestDecoder {
|
||||
RequestType.WITHDRAWAL,
|
||||
WithdrawalRequestDecoder::decode,
|
||||
RequestType.DEPOSIT,
|
||||
DepositRequestDecoder::decode);
|
||||
DepositRequestDecoder::decode,
|
||||
RequestType.CONSOLIDATION,
|
||||
ConsolidationRequestDecoder::decode);
|
||||
|
||||
/**
|
||||
* Decodes a request from its RLP encoded bytes.
|
||||
|
||||
@@ -38,7 +38,9 @@ public class RequestEncoder {
|
||||
RequestType.WITHDRAWAL,
|
||||
WithdrawalRequestEncoder::encode,
|
||||
RequestType.DEPOSIT,
|
||||
DepositRequestEncoder::encode);
|
||||
DepositRequestEncoder::encode,
|
||||
RequestType.CONSOLIDATION,
|
||||
ConsolidationRequestEncoder::encode);
|
||||
|
||||
/**
|
||||
* Encodes a Request into the provided RLPOutput.
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.mainnet.requests;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BLSPublicKey;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
public class ConsolidationRequestProcessor
|
||||
extends AbstractSystemCallRequestProcessor<ConsolidationRequest> {
|
||||
public static final Address CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS =
|
||||
Address.fromHexString("0x00b42dbF2194e931E80326D950320f7d9Dbeac02");
|
||||
|
||||
private static final int ADDRESS_BYTES = 20;
|
||||
private static final int PUBLIC_KEY_BYTES = 48;
|
||||
private static final int CONSOLIDATION_REQUEST_BYTES_SIZE =
|
||||
ADDRESS_BYTES + PUBLIC_KEY_BYTES + PUBLIC_KEY_BYTES;
|
||||
|
||||
/**
|
||||
* Gets the call address for consolidation requests.
|
||||
*
|
||||
* @return The call address.
|
||||
*/
|
||||
@Override
|
||||
protected Address getCallAddress() {
|
||||
return CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the bytes representing a single consolidation request.
|
||||
*
|
||||
* @return The size of the bytes representing a single consolidation request.
|
||||
*/
|
||||
@Override
|
||||
protected int getRequestBytesSize() {
|
||||
return CONSOLIDATION_REQUEST_BYTES_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a single consolidation request from the provided bytes.
|
||||
*
|
||||
* @param requestBytes The bytes representing a single consolidation request.
|
||||
* @return A parsed {@link ConsolidationRequest} object.
|
||||
*/
|
||||
@Override
|
||||
protected ConsolidationRequest parseRequest(final Bytes requestBytes) {
|
||||
final Address sourceAddress = Address.wrap(requestBytes.slice(0, ADDRESS_BYTES));
|
||||
final BLSPublicKey sourcePublicKey =
|
||||
BLSPublicKey.wrap(requestBytes.slice(ADDRESS_BYTES, PUBLIC_KEY_BYTES));
|
||||
final BLSPublicKey targetPublicKey =
|
||||
BLSPublicKey.wrap(requestBytes.slice(ADDRESS_BYTES + PUBLIC_KEY_BYTES, PUBLIC_KEY_BYTES));
|
||||
return new ConsolidationRequest(sourceAddress, sourcePublicKey, targetPublicKey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.mainnet.requests;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getConsolidationRequests;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
import org.hyperledger.besu.ethereum.core.Request;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ConsolidationRequestValidator implements RequestValidator {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConsolidationRequestValidator.class);
|
||||
|
||||
public static final int MAX_CONSOLIDATION_REQUESTS_PER_BLOCK = 1;
|
||||
|
||||
private boolean validateConsolidationRequestParameter(
|
||||
final Optional<List<ConsolidationRequest>> consolidationRequests) {
|
||||
return consolidationRequests.isPresent();
|
||||
}
|
||||
|
||||
private boolean validateConsolidationRequestsInBlock(
|
||||
final Block block, final List<ConsolidationRequest> consolidationRequests) {
|
||||
final Hash blockHash = block.getHash();
|
||||
|
||||
final List<ConsolidationRequest> consolidationRequestsInBlock =
|
||||
block
|
||||
.getBody()
|
||||
.getRequests()
|
||||
.flatMap(requests -> getConsolidationRequests(Optional.of(requests)))
|
||||
.orElse(Collections.emptyList());
|
||||
|
||||
if (consolidationRequestsInBlock.size() > MAX_CONSOLIDATION_REQUESTS_PER_BLOCK) {
|
||||
LOG.warn(
|
||||
"Block {} has more than the allowed maximum number of consolidation requests", blockHash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate ConsolidationRequests
|
||||
final boolean expectedConsolidationRequestMatch =
|
||||
consolidationRequests.equals(consolidationRequestsInBlock);
|
||||
if (!expectedConsolidationRequestMatch) {
|
||||
LOG.warn(
|
||||
"Block {} has a mismatch between block consolidations and RPC consolidation requests (in_block = {}, "
|
||||
+ "expected = {})",
|
||||
blockHash,
|
||||
consolidationRequestsInBlock,
|
||||
consolidationRequests);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(
|
||||
final Block block, final List<Request> requests, final List<TransactionReceipt> receipts) {
|
||||
var consolidationRequests =
|
||||
getConsolidationRequests(Optional.of(requests)).orElse(Collections.emptyList());
|
||||
return validateConsolidationRequestsInBlock(block, consolidationRequests);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateParameter(final Optional<List<Request>> request) {
|
||||
if (request.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
var consolidationRequests =
|
||||
RequestUtil.filterRequestsOfType(request.get(), ConsolidationRequest.class);
|
||||
return validateConsolidationRequestParameter(Optional.of(consolidationRequests));
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ public class MainnetRequestsValidator {
|
||||
final Address depositContractAddress) {
|
||||
return new RequestsValidatorCoordinator.Builder()
|
||||
.addValidator(RequestType.WITHDRAWAL, new WithdrawalRequestValidator())
|
||||
.addValidator(RequestType.CONSOLIDATION, new ConsolidationRequestValidator())
|
||||
.addValidator(RequestType.DEPOSIT, new DepositRequestValidator(depositContractAddress))
|
||||
.build();
|
||||
}
|
||||
@@ -30,6 +31,7 @@ public class MainnetRequestsValidator {
|
||||
final Address depositContractAddress) {
|
||||
return new RequestProcessorCoordinator.Builder()
|
||||
.addProcessor(RequestType.WITHDRAWAL, new WithdrawalRequestProcessor())
|
||||
.addProcessor(RequestType.CONSOLIDATION, new ConsolidationRequestProcessor())
|
||||
.addProcessor(RequestType.DEPOSIT, new DepositRequestProcessor(depositContractAddress))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.mainnet.requests;
|
||||
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
import org.hyperledger.besu.ethereum.core.DepositRequest;
|
||||
import org.hyperledger.besu.ethereum.core.Request;
|
||||
import org.hyperledger.besu.ethereum.core.WithdrawalRequest;
|
||||
@@ -52,23 +53,33 @@ public class RequestUtil {
|
||||
return requests.map(r -> filterRequestsOfType(r, WithdrawalRequest.class));
|
||||
}
|
||||
|
||||
public static Optional<List<ConsolidationRequest>> getConsolidationRequests(
|
||||
final Optional<List<Request>> requests) {
|
||||
return requests.map(r -> filterRequestsOfType(r, ConsolidationRequest.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines two optional lists of requests into a single optional list.
|
||||
* Combines multiple optional lists of requests into a single optional list.
|
||||
*
|
||||
* @param maybeDepositRequests Optional list of deposit requests.
|
||||
* @param maybeWithdrawalRequest Optional list of withdrawal requests.
|
||||
* @return An Optional containing the combined list of requests, or an empty Optional if both
|
||||
* inputs are empty.
|
||||
* @param maybeConsolidationRequest Optional list of withdrawal requests.
|
||||
* @return An Optional containing the combined list of requests, or an empty Optional if all input
|
||||
* lists are empty.
|
||||
*/
|
||||
public static Optional<List<Request>> combine(
|
||||
final Optional<List<Request>> maybeDepositRequests,
|
||||
final Optional<List<Request>> maybeWithdrawalRequest) {
|
||||
if (maybeDepositRequests.isEmpty() && maybeWithdrawalRequest.isEmpty()) {
|
||||
final Optional<List<Request>> maybeWithdrawalRequest,
|
||||
final Optional<List<Request>> maybeConsolidationRequest) {
|
||||
if (maybeDepositRequests.isEmpty()
|
||||
&& maybeWithdrawalRequest.isEmpty()
|
||||
&& maybeConsolidationRequest.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
List<Request> requests = new ArrayList<>();
|
||||
maybeDepositRequests.ifPresent(requests::addAll);
|
||||
maybeWithdrawalRequest.ifPresent(requests::addAll);
|
||||
maybeConsolidationRequest.ifPresent(requests::addAll);
|
||||
return Optional.of(requests);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.core.encoding;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BLSPublicKey;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
import org.hyperledger.besu.ethereum.core.Request;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ConsolidationRequestDecoderTest {
|
||||
|
||||
@Test
|
||||
public void shouldDecodeWithdrawalRequest() {
|
||||
final ConsolidationRequest expectedConsolidationRequest =
|
||||
new ConsolidationRequest(
|
||||
Address.fromHexString("0x814FaE9f487206471B6B0D713cD51a2D35980000"),
|
||||
BLSPublicKey.fromHexString(
|
||||
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
|
||||
BLSPublicKey.fromHexString(
|
||||
"0xa09a4a15bf67b328c9b101d09e5c6ee6672978f7ad9ef0d9e2c457aee99223555d8601f0cb3bcc4ce1af9864779a416e"));
|
||||
|
||||
final BytesValueRLPOutput out = new BytesValueRLPOutput();
|
||||
expectedConsolidationRequest.writeTo(out);
|
||||
|
||||
final Request decodedWithdrawalRequest = RequestDecoder.decode(RLP.input(out.encoded()));
|
||||
|
||||
Assertions.assertThat(decodedWithdrawalRequest).isEqualTo(expectedConsolidationRequest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.core.encoding;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BLSPublicKey;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ConsolidationRequestEncoderTest {
|
||||
|
||||
private final String expectedEncodedBytes =
|
||||
"f87794763c396673f9c391dce3361a9a71c8e161388000b0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416eb0a09a4a15bf67b328c9b101d09e5c6ee6672978f7ad9ef0d9e2c457aee99223555d8601f0cb3bcc4ce1af9864779a416e";
|
||||
|
||||
final ConsolidationRequest consolidationRequest =
|
||||
new ConsolidationRequest(
|
||||
Address.fromHexString("0x763c396673F9c391DCe3361A9A71C8E161388000"),
|
||||
BLSPublicKey.fromHexString(
|
||||
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
|
||||
BLSPublicKey.fromHexString(
|
||||
"0xa09a4a15bf67b328c9b101d09e5c6ee6672978f7ad9ef0d9e2c457aee99223555d8601f0cb3bcc4ce1af9864779a416e"));
|
||||
|
||||
@Test
|
||||
void shouldEncodeConsolidationRequest() {
|
||||
final Bytes encoded = ConsolidationRequestEncoder.encodeOpaqueBytes(consolidationRequest);
|
||||
assertThat(encoded).isEqualTo(Bytes.fromHexString(expectedEncodedBytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldEncodeRequest() {
|
||||
final Bytes encoded = RequestEncoder.encodeOpaqueBytes(consolidationRequest);
|
||||
assertThat(encoded)
|
||||
.isEqualTo(
|
||||
Bytes.fromHexString(
|
||||
String.format(
|
||||
"0x%02X%s",
|
||||
consolidationRequest.getType().getSerializedType(), expectedEncodedBytes)));
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt64;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DepositRequestRequestDecoderTest {
|
||||
class DepositRequestDecoderTest {
|
||||
@Test
|
||||
void shouldDecodeDeposit() {
|
||||
final DepositRequest expectedDepositRequest =
|
||||
@@ -26,7 +26,7 @@ import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt64;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DepositRequestRequestEncoderTest {
|
||||
class DepositRequestEncoderTest {
|
||||
private final String expectedDepositEncodedBytes =
|
||||
"f8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501";
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.mainnet;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.mainnet.requests.ConsolidationRequestValidator.MAX_CONSOLIDATION_REQUESTS_PER_BLOCK;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BLSPublicKey;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
import org.hyperledger.besu.ethereum.core.Request;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.bytes.Bytes48;
|
||||
|
||||
public class ConsolidationRequestValidatorTestFixtures {
|
||||
|
||||
private static final BlockDataGenerator blockDataGenerator = new BlockDataGenerator();
|
||||
|
||||
static ConsolidationRequestTestParameter
|
||||
blockWithConsolidationRequestsAndWithdrawalRequestsRoot() {
|
||||
final ConsolidationRequest consolidationRequest = createConsolidationRequest();
|
||||
final Optional<List<Request>> maybeConsolidationRequests =
|
||||
Optional.of(List.of(consolidationRequest));
|
||||
|
||||
final BlockDataGenerator.BlockOptions blockOptions =
|
||||
BlockDataGenerator.BlockOptions.create()
|
||||
.setRequestsRoot(BodyValidation.requestsRoot(maybeConsolidationRequests.get()))
|
||||
.setRequests(maybeConsolidationRequests);
|
||||
final Block block = blockDataGenerator.block(blockOptions);
|
||||
|
||||
return new ConsolidationRequestTestParameter(
|
||||
"Block with consolidation requests and withdrawal_requests_root",
|
||||
block,
|
||||
Optional.of(List.of(consolidationRequest)));
|
||||
}
|
||||
|
||||
static ConsolidationRequestTestParameter blockWithConsolidationRequestsMismatch() {
|
||||
final ConsolidationRequest consolidationRequest = createConsolidationRequest();
|
||||
|
||||
final Optional<List<Request>> requests =
|
||||
Optional.of(List.of(consolidationRequest, consolidationRequest));
|
||||
|
||||
final BlockDataGenerator.BlockOptions blockOptions =
|
||||
BlockDataGenerator.BlockOptions.create()
|
||||
.setRequestsRoot(BodyValidation.requestsRoot(requests.get()))
|
||||
.setRequests(requests);
|
||||
final Block block = blockDataGenerator.block(blockOptions);
|
||||
|
||||
return new ConsolidationRequestTestParameter(
|
||||
"Block with consolidation requests mismatch",
|
||||
block,
|
||||
Optional.of(List.of(consolidationRequest, consolidationRequest)),
|
||||
List.of(createConsolidationRequest()));
|
||||
}
|
||||
|
||||
static ConsolidationRequestTestParameter blockWithMoreThanMaximumConsolidationRequests() {
|
||||
final List<ConsolidationRequest> consolidationRequests =
|
||||
IntStream.range(0, MAX_CONSOLIDATION_REQUESTS_PER_BLOCK + 1)
|
||||
.mapToObj(__ -> createConsolidationRequest())
|
||||
.toList();
|
||||
|
||||
final Optional<List<ConsolidationRequest>> maybeConsolidationRequest =
|
||||
Optional.of(consolidationRequests);
|
||||
final Optional<List<Request>> maybeRequests =
|
||||
Optional.of(consolidationRequests.stream().map(r -> (Request) r).toList());
|
||||
|
||||
final BlockDataGenerator.BlockOptions blockOptions =
|
||||
BlockDataGenerator.BlockOptions.create()
|
||||
.setRequestsRoot(BodyValidation.requestsRoot(maybeRequests.get()))
|
||||
.setRequests(maybeRequests);
|
||||
final Block block = blockDataGenerator.block(blockOptions);
|
||||
|
||||
return new ConsolidationRequestTestParameter(
|
||||
"Block with more than maximum consolidation requests", block, maybeConsolidationRequest);
|
||||
}
|
||||
|
||||
static ConsolidationRequest createConsolidationRequest() {
|
||||
return new ConsolidationRequest(
|
||||
Address.extract(Bytes32.random()),
|
||||
BLSPublicKey.wrap(Bytes48.random()),
|
||||
BLSPublicKey.wrap(Bytes48.random()));
|
||||
}
|
||||
|
||||
static class ConsolidationRequestTestParameter {
|
||||
|
||||
String description;
|
||||
Block block;
|
||||
Optional<List<ConsolidationRequest>> maybeConsolidationRequest;
|
||||
List<ConsolidationRequest> expectedConsolidationRequest;
|
||||
|
||||
public ConsolidationRequestTestParameter(
|
||||
final String description,
|
||||
final Block block,
|
||||
final Optional<List<ConsolidationRequest>> maybeConsolidationRequest) {
|
||||
this(
|
||||
description,
|
||||
block,
|
||||
maybeConsolidationRequest,
|
||||
maybeConsolidationRequest.orElseGet(List::of));
|
||||
}
|
||||
|
||||
public ConsolidationRequestTestParameter(
|
||||
final String description,
|
||||
final Block block,
|
||||
final Optional<List<ConsolidationRequest>> maybeConsolidationRequest,
|
||||
final List<ConsolidationRequest> expectedConsolidationRequest) {
|
||||
this.description = description;
|
||||
this.block = block;
|
||||
this.maybeConsolidationRequest = maybeConsolidationRequest;
|
||||
this.expectedConsolidationRequest = expectedConsolidationRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.mainnet;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.ethereum.mainnet.ConsolidationRequestValidatorTestFixtures.blockWithConsolidationRequestsAndWithdrawalRequestsRoot;
|
||||
import static org.hyperledger.besu.ethereum.mainnet.ConsolidationRequestValidatorTestFixtures.blockWithConsolidationRequestsMismatch;
|
||||
import static org.hyperledger.besu.ethereum.mainnet.ConsolidationRequestValidatorTestFixtures.blockWithMoreThanMaximumConsolidationRequests;
|
||||
|
||||
import org.hyperledger.besu.ethereum.core.Request;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ConsolidationRequestValidatorTestFixtures.ConsolidationRequestTestParameter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.requests.ConsolidationRequestValidator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class PragueConsolidationRequestValidatorTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}: {0}")
|
||||
@MethodSource("paramsForValidateConsolidationRequestParameter")
|
||||
public void validateConsolidationRequestParameter(
|
||||
final String description,
|
||||
final Optional<List<Request>> maybeRequests,
|
||||
final boolean expectedValidity) {
|
||||
assertThat(new ConsolidationRequestValidator().validateParameter(maybeRequests))
|
||||
.isEqualTo(expectedValidity);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> paramsForValidateConsolidationRequestParameter() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
"Allowed ConsolidationRequests - validating empty ConsolidationRequests",
|
||||
Optional.empty(),
|
||||
true),
|
||||
Arguments.of(
|
||||
"Allowed ConsolidationRequests - validating present ConsolidationRequests",
|
||||
Optional.of(List.of()),
|
||||
true));
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{index}: {0}")
|
||||
@MethodSource("validateConsolidationRequestsInBlockParamsForPrague")
|
||||
public void validateConsolidationRequestsInBlock_WhenPrague(
|
||||
final ConsolidationRequestTestParameter param, final boolean expectedValidity) {
|
||||
assertThat(
|
||||
new ConsolidationRequestValidator()
|
||||
.validate(
|
||||
param.block, new ArrayList<>(param.expectedConsolidationRequest), List.of()))
|
||||
.isEqualTo(expectedValidity);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> validateConsolidationRequestsInBlockParamsForPrague() {
|
||||
return Stream.of(
|
||||
Arguments.of(blockWithConsolidationRequestsAndWithdrawalRequestsRoot(), true),
|
||||
Arguments.of(blockWithConsolidationRequestsMismatch(), false),
|
||||
Arguments.of(blockWithMoreThanMaximumConsolidationRequests(), false));
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import org.hyperledger.besu.datatypes.VersionedHash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest;
|
||||
import org.hyperledger.besu.ethereum.core.DepositRequest;
|
||||
import org.hyperledger.besu.ethereum.core.Request;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
@@ -495,15 +496,25 @@ public class T8nExecutor {
|
||||
obj.put("index", deposit.getIndex().toHexString());
|
||||
});
|
||||
|
||||
var withdrawlRequests = resultObject.putArray("withdrawalRequests");
|
||||
var withdrawalRequests = resultObject.putArray("withdrawalRequests");
|
||||
RequestUtil.filterRequestsOfType(maybeRequests.orElse(List.of()), WithdrawalRequest.class)
|
||||
.forEach(
|
||||
wr -> {
|
||||
var obj = withdrawlRequests.addObject();
|
||||
var obj = withdrawalRequests.addObject();
|
||||
obj.put("sourceAddress", wr.getSourceAddress().toHexString());
|
||||
obj.put("validatorPubkey", wr.getValidatorPubkey().toHexString());
|
||||
obj.put("amount", wr.getAmount().toHexString());
|
||||
});
|
||||
|
||||
var consolidationRequests = resultObject.putArray("consolidationRequests");
|
||||
RequestUtil.filterRequestsOfType(maybeRequests.orElse(List.of()), ConsolidationRequest.class)
|
||||
.forEach(
|
||||
cr -> {
|
||||
var obj = consolidationRequests.addObject();
|
||||
obj.put("sourceAddress", cr.getSourceAddress().toHexString());
|
||||
obj.put("sourcePubkey", cr.getSourcePubkey().toHexString());
|
||||
obj.put("targetPubkey", cr.getTargetPubkey().toHexString());
|
||||
});
|
||||
}
|
||||
|
||||
worldState.persist(blockHeader);
|
||||
|
||||
@@ -172,6 +172,11 @@
|
||||
"balance": "0x3782dace9d9000000",
|
||||
"nonce": "0x1"
|
||||
},
|
||||
"0x00a3ca265ebcb825b45f985a16cefb49958ce017": {
|
||||
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x1"
|
||||
},
|
||||
"0x000f3df6d732807ef1319fb7b8bb8522d0beac02": {
|
||||
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500",
|
||||
"storage": {
|
||||
@@ -180,11 +185,6 @@
|
||||
"balance": "0x0",
|
||||
"nonce": "0x1"
|
||||
},
|
||||
"0x00a3ca265ebcb825b45f985a16cefb49958ce017": {
|
||||
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x1"
|
||||
},
|
||||
"0x0aae40965e6800cd9b1f4b05ff21581047e3f91e": {
|
||||
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460575767ffffffffffffffff5f3511605357600143035f3511604b575f35612000014311604b57611fff5f3516545f5260205ff35b5f5f5260205ff35b5f5ffd5b5f35611fff60014303165500",
|
||||
"storage": {
|
||||
@@ -282,7 +282,8 @@
|
||||
"index": "0x0000000000000001"
|
||||
}
|
||||
],
|
||||
"withdrawalRequests": []
|
||||
"withdrawalRequests": [],
|
||||
"consolidationRequests":[]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,6 +314,7 @@
|
||||
"amount": "0x0000000000000000"
|
||||
}
|
||||
],
|
||||
"consolidationRequests":[],
|
||||
"stateRoot": "0xf63d7552dc407993393315e99272781d04eedfcf369a1acd3e386d1e6710229d",
|
||||
"txRoot": "0x8521df63211790726b6f1a437bb0fd4b27c00e13e7678d324c4cfddb8d834ad2",
|
||||
"receiptsRoot": "0x4bd8bd5580caf4ed45f873794ad7ff9d6fd2363ae529269b17b891b68d349d75",
|
||||
|
||||
@@ -90,10 +90,10 @@ public class BlockchainReferenceTestTools {
|
||||
params.ignore(
|
||||
"UncleFromSideChain_(Merge|Paris|Shanghai|Cancun|Prague|Osaka|Amsterdam|Bogota|Polis|Bangkok)");
|
||||
|
||||
// EOF tests don't have Prague stuff like deopsits right now
|
||||
// EOF tests don't have Prague stuff like deposits right now
|
||||
params.ignore("/stEOF/");
|
||||
|
||||
// None of the Prague tests have withdrawls and deposits handling
|
||||
// None of the Prague tests have withdrawals and deposits handling
|
||||
params.ignore("\\[Prague\\]");
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ Calculated : ${currentHash}
|
||||
tasks.register('checkAPIChanges', FileStateChecker) {
|
||||
description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
|
||||
files = sourceSets.main.allJava.files
|
||||
knownHash = 'yH50m+z1tnzshJQPdwR86pb2EU3m6iZxwkqoy/5spcs='
|
||||
knownHash = 'Yv6CY8fh0yrIz3Q8Moy/j1TNGL+O8Mewp4SIgM1JE6M='
|
||||
}
|
||||
check.dependsOn('checkAPIChanges')
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.plugin.data;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.PublicKey;
|
||||
import org.hyperledger.besu.plugin.Unstable;
|
||||
|
||||
/** A consolidation request is an operation sent to the Beacon Node for processing. */
|
||||
@Unstable
|
||||
public interface ConsolidationRequest {
|
||||
|
||||
/**
|
||||
* Withdrawal credential (0x01) associated with the validator
|
||||
*
|
||||
* @return withdrawal credential address
|
||||
*/
|
||||
Address getSourceAddress();
|
||||
|
||||
/**
|
||||
* Public key of the address that sends the consolidation
|
||||
*
|
||||
* @return public key of sender
|
||||
*/
|
||||
PublicKey getSourcePubkey();
|
||||
|
||||
/**
|
||||
* Public key of the address to receives the consolidation
|
||||
*
|
||||
* @return public key of target
|
||||
*/
|
||||
PublicKey getTargetPubkey();
|
||||
}
|
||||
Reference in New Issue
Block a user