-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement deserialization of newPayloadV2 request
- Loading branch information
Showing
14 changed files
with
388 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
const hexutils = @import("./hexutils.zig"); | ||
pub const prefixedhex2hash = hexutils.prefixedhex2hash; | ||
pub const prefixedhex2byteslice = hexutils.prefixedhex2byteslice; | ||
pub const prefixedhex2u64 = hexutils.prefixedhex2u64; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
const std = @import("std"); | ||
const fmt = std.fmt; | ||
const Allocator = std.mem.Allocator; | ||
|
||
// This function turns an optionally '0x'-prefixed hex string | ||
// to a types.Hash32 | ||
pub fn prefixedhex2hash(dst: []u8, src: []const u8) !void { | ||
if (src.len < 2 or src.len % 2 != 0) { | ||
return error.InvalidInput; | ||
} | ||
var skip0x: usize = if (src[1] == 'X' or src[1] == 'x') 2 else 0; | ||
if (src[skip0x..].len != 2 * dst.len) { | ||
return error.InvalidOutputLength; | ||
} | ||
_ = try fmt.hexToBytes(dst, src[skip0x..]); | ||
} | ||
|
||
// This function turns an optionally '0x'-prefixed hex string | ||
// to a byte slice | ||
pub fn prefixedhex2byteslice(allocator: Allocator, src: []const u8) ![]u8 { | ||
// TODO catch the 0x0 corner case | ||
if (src.len < 2 or src.len % 2 != 0) { | ||
return error.InvalidInput; | ||
} | ||
var skip0x: usize = if (src[1] == 'X' or src[1] == 'x') 2 else 0; | ||
// TODO when refactoring, ensure the alloc is also made in the equivalent for prefixedhex2hash | ||
var dst: []u8 = try allocator.alloc(u8, src[skip0x..].len / 2); | ||
|
||
_ = try fmt.hexToBytes(dst[0..], src[skip0x..]); | ||
|
||
return dst; | ||
} | ||
|
||
// This function turns an optionally '0x'-prefixed hex string | ||
// to a u64 | ||
pub fn prefixedhex2u64(src: []const u8) !u64 { | ||
// execution engine integers can be odd-length :facepalm: | ||
if (src.len < 3) { | ||
return error.InvalidInput; | ||
} | ||
|
||
var skip0x: usize = if (src[1] == 'X' or src[1] == 'x') 2 else 0; | ||
|
||
return std.fmt.parseInt(u64, src[skip0x..], 16); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
const std = @import("std"); | ||
const fmt = std.fmt; | ||
const Allocator = std.mem.Allocator; | ||
pub const execution_payload = @import("./execution_payload.zig"); | ||
const ExecutionPayload = execution_payload.ExecutionPayload; | ||
const common = @import("../common/common.zig"); | ||
|
||
// This is an intermediate structure used to deserialize the hex strings | ||
// from the JSON request. I have seen some zig libraries that can do this | ||
// out of the box, but it seems that approach hasn't been merged into the | ||
// std yet. | ||
// Because the JSON libary won't be able to deserialize a union unless | ||
// the union is explicitly named, all possible object keys are declared in | ||
// this object, and the caller is responsible for sifting through them by | ||
// calling any of the `to_*` method, based on the context. | ||
const AllPossibleExecutionParams = struct { | ||
parentHash: []const u8, | ||
feeRecipient: []const u8, | ||
stateRoot: []const u8, | ||
receiptsRoot: []const u8, | ||
logsBloom: []const u8, | ||
prevRandao: []const u8, | ||
blockNumber: []const u8, | ||
gasLimit: []const u8, | ||
gasUsed: []const u8, | ||
timestamp: []const u8, | ||
extraData: []const u8, | ||
baseFeePerGas: []const u8, | ||
blockHash: []const u8, | ||
transactions: [][]const u8, | ||
|
||
pub fn to_execution_payload(self: *const AllPossibleExecutionParams, allocator: Allocator) !ExecutionPayload { | ||
var transactions: [][]const u8 = &[_][]const u8{}; | ||
if (self.transactions.len > 0) { | ||
transactions = try allocator.alloc([]const u8, self.transactions.len); | ||
for (self.transactions, 0..) |tx, txidx| { | ||
transactions[txidx] = try common.prefixedhex2byteslice(allocator, tx); | ||
} | ||
} | ||
|
||
var ret = ExecutionPayload{ | ||
.parentHash = undefined, | ||
.feeRecipient = undefined, | ||
.stateRoot = undefined, | ||
.receiptsRoot = undefined, | ||
.prevRandao = undefined, | ||
.extraData = try common.prefixedhex2byteslice(allocator, self.extraData), | ||
.blockHash = undefined, | ||
.logsBloom = undefined, | ||
.blockNumber = try common.prefixedhex2u64(self.blockNumber), | ||
.gasLimit = try common.prefixedhex2u64(self.gasLimit), | ||
.gasUsed = try common.prefixedhex2u64(self.gasUsed), | ||
.timestamp = try common.prefixedhex2u64(self.timestamp), | ||
.baseFeePerGas = try common.prefixedhex2u64(self.baseFeePerGas), | ||
.transactions = transactions, | ||
.withdrawals = null, | ||
.blobGasUsed = null, | ||
.excessBlobGas = null, | ||
.allocator = allocator, | ||
}; | ||
|
||
_ = try common.prefixedhex2hash(ret.parentHash[0..], self.parentHash); | ||
_ = try common.prefixedhex2hash(ret.feeRecipient[0..], self.feeRecipient); | ||
_ = try common.prefixedhex2hash(ret.stateRoot[0..], self.stateRoot); | ||
_ = try common.prefixedhex2hash(ret.receiptsRoot[0..], self.receiptsRoot); | ||
_ = try common.prefixedhex2hash(ret.logsBloom[0..], self.logsBloom); | ||
_ = try common.prefixedhex2hash(ret.prevRandao[0..], self.prevRandao); | ||
_ = try common.prefixedhex2hash(ret.blockHash[0..], self.blockHash); | ||
|
||
return ret; | ||
} | ||
}; | ||
|
||
pub const EngineAPIRequest = struct { | ||
jsonrpc: []const u8, | ||
id: u64, | ||
method: []const u8, | ||
params: []const AllPossibleExecutionParams, | ||
}; | ||
|
||
test "deserialize sample engine_newPayloadV2" { | ||
const json = std.json; | ||
const expect = std.testing.expect; | ||
|
||
const filePath = "./src/engine_api/test_req.json"; | ||
|
||
const file = try std.fs.cwd().openFile(filePath, .{}); | ||
defer file.close(); | ||
|
||
const stat = try file.stat(); | ||
|
||
var buffer = try std.testing.allocator.alloc(u8, stat.size); | ||
defer std.testing.allocator.free(buffer); | ||
_ = try file.readAll(buffer); | ||
|
||
const payload = try json.parseFromSlice(EngineAPIRequest, std.testing.allocator, buffer, .{ .ignore_unknown_fields = true }); | ||
defer payload.deinit(); | ||
|
||
try expect(std.mem.eql(u8, payload.value.method, "engine_newPayloadV2")); | ||
const execution_payload_json = payload.value.params[0]; | ||
var ep = try execution_payload_json.to_execution_payload(std.testing.allocator); | ||
try execution_payload.newPayloadV2Handler(&ep, std.testing.allocator); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
const std = @import("std"); | ||
const types = @import("../types/types.zig"); | ||
const Allocator = std.mem.Allocator; | ||
|
||
pub const ExecutionPayload = struct { | ||
parentHash: types.Hash32, | ||
feeRecipient: types.Address, | ||
stateRoot: types.Hash32, | ||
receiptsRoot: types.Hash32, | ||
logsBloom: [256]u8, | ||
prevRandao: types.Hash32, | ||
blockNumber: u64, | ||
gasLimit: u64, | ||
gasUsed: u64, | ||
timestamp: u64, | ||
extraData: []const u8, | ||
baseFeePerGas: u256, | ||
blockHash: types.Hash32, | ||
transactions: [][]const u8, | ||
|
||
withdrawals: ?[]types.Withdrawal, | ||
blobGasUsed: ?u64, | ||
excessBlobGas: ?u64, | ||
// executionWitness : ?types.ExecutionWitness, | ||
|
||
allocator: Allocator, | ||
|
||
pub fn to_block(self: *const ExecutionPayload) types.Block { | ||
return types.Block{ | ||
.header = types.BlockHeader{ | ||
.parent_hash = self.parentHash, | ||
.uncle_hash = types.empty_uncle_hash, | ||
.fee_recipient = self.feeRecipient, | ||
.state_root = self.stateRoot, | ||
.receipts_root = self.receiptsRoot, | ||
.logs_bloom = self.logsBloom, | ||
.prev_randao = self.prevRandao, | ||
.block_number = @intCast(self.blockNumber), | ||
.gas_limit = @intCast(self.gasLimit), | ||
.gas_used = self.gasUsed, | ||
.timestamp = @intCast(self.timestamp), | ||
.extra_data = self.extraData, | ||
.base_fee_per_gas = self.baseFeePerGas, | ||
.transactions_root = [_]u8{0} ** 32, | ||
.mix_hash = 0, | ||
.nonce = [_]u8{0} ** 8, | ||
.blob_gas_used = null, | ||
.withdrawals_root = null, | ||
.excess_blob_gas = null, | ||
}, | ||
// .blockHash = self.blockHash, | ||
// .transactions = self.transactions, | ||
// .withdrawals = self.withdrawals, | ||
}; | ||
} | ||
|
||
pub fn deinit(self: *ExecutionPayload, allocator: std.mem.Allocator) void { | ||
if (self.extraData.len > 0) { | ||
allocator.free(self.extraData); | ||
} | ||
} | ||
}; | ||
|
||
pub fn newPayloadV2Handler(params: *ExecutionPayload, allocator: std.mem.Allocator) !void { | ||
// TODO reconstruct the proof from the (currently undefined) execution witness | ||
// and verify it. Then execute the block and return the result. | ||
// vm.run_block(params.to_block(), params.transactions); | ||
|
||
// But so far, just print the content of the payload | ||
std.log.info("newPayloadV2Handler: {any}", .{params}); | ||
|
||
var block = params.to_block(); | ||
std.debug.print("block number={}\n", .{block.header.block_number}); | ||
params.deinit(allocator); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"jsonrpc": "2.0", | ||
"id": 60282, | ||
"method": "engine_newPayloadV2", | ||
"params": [ | ||
{ | ||
"parentHash": "0x522930864dc2f6569f4d4b92f40001fe6752727ff53db5cb5c5ffd51d3cc53e4", | ||
"feeRecipient": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", | ||
"stateRoot": "0x27bb13dc19c41288dd29236b27baac49338c466b8c0eb44fb4c0c0083dfb214a", | ||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", | ||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", | ||
"prevRandao": "0x8ad449de1358704350f28598677be5c4cd609b42d31653b967f615b47ad1e63e", | ||
"blockNumber": "0x112b8", | ||
"gasLimit": "0x1c9c380", | ||
"gasUsed": "0x0", | ||
"timestamp": "0x65361030", | ||
"extraData": "0xd983010c01846765746889676f312e32302e3130856c696e7578", | ||
"baseFeePerGas": "0x7", | ||
"blockHash": "0x56f5dba155cc4317aaa479f26f135dd543d5977026e83a9bb6b0ae895b4c7a10", | ||
"transactions": [] | ||
}]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.