Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gen_arg test with arbitrary block #182

Open
tcoratger opened this issue Nov 30, 2024 · 2 comments
Open

Add gen_arg test with arbitrary block #182

tcoratger opened this issue Nov 30, 2024 · 2 comments
Assignees
Labels
good first issue Good for newcomers

Comments

@tcoratger
Copy link
Collaborator

In #127, we tested the KethPayload function with a simplified harcoded block for which we knew exactly the expected behavior:

fn test_gen_arg_block() {
// Initialize a new block header
let header = Header {
parent_hash: B256::from_str(
"0x02a4bfb03275efd1bf926bcbccc1c12ef1ed723414c1196b75c33219355c7180",
)
.unwrap(),
ommers_hash: B256::from_str(
"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
)
.unwrap(),
beneficiary: Address::from_str("0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap(),
state_root: B256::from_str(
"0x2f79dbc20b78bcd7a771a9eb6b25a4af69724085c97be69a95ba91187e66a9c0",
)
.unwrap(),
transactions_root: B256::from_str(
"0x5f3c4c1da4f0b2351fbb60b9e720d481ce0706b5aa697f10f28efbbab54e6ac8",
)
.unwrap(),
receipts_root: B256::from_str(
"0xf44202824894394d28fa6c8c8e3ef83e1adf05405da06240c2ce9ca461e843d1",
)
.unwrap(),
logs_bloom: Bloom::default(),
difficulty: U256::ZERO,
number: 1,
gas_limit: 0x000f_4240,
gas_used: 0x0001_56f8,
timestamp: 0x6490_3c57,
extra_data: Bytes::from_static(&hex!("00")),
mix_hash: B256::from_str(
"0x0000000000000000000000000000000000000000000000000000000000020000",
)
.unwrap(),
nonce: B64::from_str("0x0000000000000000").unwrap(),
base_fee_per_gas: Some(0x0a),
withdrawals_root: Some(
B256::from_str(
"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
)
.unwrap(),
),
blob_gas_used: Some(0x00),
excess_blob_gas: Some(0x00),
parent_beacon_block_root: Some(
B256::from_str(
"0x0000000000000000000000000000000000000000000000000000000000000000",
)
.unwrap(),
),
requests_hash: None,
};
// Initialize the block hash
let block_hash =
B256::from_str("0x46e317ac1d4c1a14323d9ef994c0f0813c6a90af87113a872ca6bcfcea86edba")
.unwrap();
// Seal the header with the block hash
let sealed_header = SealedHeader::new(header, block_hash);
// Generate some transaction input bytes
let transaction_data = Bytes::from_static(&hex!("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
// Create a transaction with a signature but no hash
let transaction_no_hash = TransactionSignedNoHash {
transaction: Transaction::Legacy(TxLegacy {
chain_id: None,
nonce: 0x00,
gas_price: 0x0a,
gas_limit: 0x000f_4240,
to: revm_primitives::TxKind::Call(
Address::from_str("0x000000000000000000000000000000000000c0de").unwrap(),
),
value: U256::from(0x00),
input: transaction_data,
}),
signature: PrimitiveSignature::from_scalars_and_parity(
B256::from_str(
"0xf225c2292ba248fe3ed544f7d45dd4172337ba41dc480c3b17af63e03d281daf",
)
.unwrap(),
B256::from_str(
"0x35360ae92ae767c1d0a9e0358e4398174b10eeea046bceedf323e7bf3b17c652",
)
.unwrap(),
Parity::try_from(0x1c_u64).unwrap().y_parity(),
),
};
// Add the transaction hash
let transaction = transaction_no_hash.with_hash();
// Seal the block
let sealed_block = SealedBlock {
header: sealed_header,
body: BlockBody {
transactions: vec![transaction.clone(), transaction],
ommers: vec![],
withdrawals: Some(vec![].into()),
},
};
// Transform the sealed block into a KethBlock
let keth_block: KethBlock = sealed_block.into();
// Transform the KethBlock into a KethPayload
let keth_payload: KethPayload = keth_block.clone().into();
// Create a new instance of the VirtualMachine.
let mut vm = VirtualMachine::new(false);
// Call gen_arg to encode the block payload and write it to the VM's memory.
let result = keth_payload.gen_arg(&mut vm);
// Retrieve the resulting pointer to the memory segment for the complex Nested payload.
let ptr = match result.expect("Failed to gen_arg the block payload") {
MaybeRelocatable::RelocatableValue(relocatable) => relocatable,
MaybeRelocatable::Int(_) => panic!("Expected a valid pointer"),
};
// Extract the block header pointer
let header_ptr = vm.get_maybe(&ptr).unwrap().get_relocatable().unwrap();
// Transaction count
assert_eq!(
vm.get_maybe(&(ptr + 1usize).unwrap()),
Some(keth_block.clone().transactions_len.0)
);
let transaction_ptr =
vm.get_maybe(&(ptr + 2usize).unwrap()).unwrap().get_relocatable().unwrap();
// Block header fields
// The parent hash as U256:
// - Low
// - High
assert_eq!(vm.get_maybe(&header_ptr), Some(keth_block.block_header.parent_hash.low.0));
assert_eq!(
vm.get_maybe(&(header_ptr + 1usize).unwrap()),
Some(keth_block.block_header.parent_hash.high.0)
);
// The ommers hash as U256:
// - Low
// - High
assert_eq!(
vm.get_maybe(&(header_ptr + 2usize).unwrap()),
Some(keth_block.block_header.ommers_hash.low.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 3usize).unwrap()),
Some(keth_block.block_header.ommers_hash.high.0)
);
// The beneficiary as Address with a single Felt
assert_eq!(
vm.get_maybe(&(header_ptr + 4usize).unwrap()),
Some(keth_block.block_header.coinbase.0)
);
// The state root as U256:
// - Low
// - High
assert_eq!(
vm.get_maybe(&(header_ptr + 5usize).unwrap()),
Some(keth_block.block_header.state_root.low.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 6usize).unwrap()),
Some(keth_block.block_header.state_root.high.0)
);
// The transactions root as U256:
// - Low
// - High
assert_eq!(
vm.get_maybe(&(header_ptr + 7usize).unwrap()),
Some(keth_block.block_header.transactions_root.low.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 8usize).unwrap()),
Some(keth_block.block_header.transactions_root.high.0)
);
// The receipt root as U256:
// - Low
// - High
assert_eq!(
vm.get_maybe(&(header_ptr + 9usize).unwrap()),
Some(keth_block.block_header.receipt_root.low.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 10usize).unwrap()),
Some(keth_block.block_header.receipt_root.high.0)
);
// The withdrawal root as an Option of U256*:
// - is_some
// - address of the U256
assert_eq!(
vm.get_maybe(&(header_ptr + 11usize).unwrap()),
Some(keth_block.block_header.withdrawals_root.is_some.0)
);
let withdrawal_root_ptr =
vm.get_maybe(&(header_ptr + 12usize).unwrap()).unwrap().get_relocatable().unwrap();
// Withdrawal root U256 pointer:
// - Low
// - High
assert_eq!(
vm.get_maybe(&withdrawal_root_ptr),
Some(keth_block.block_header.withdrawals_root.value.data[0].0.clone())
);
assert_eq!(
vm.get_maybe(&(withdrawal_root_ptr + 1usize).unwrap()),
Some(keth_block.block_header.withdrawals_root.value.data[1].0.clone())
);
assert_eq!(vm.get_maybe(&(withdrawal_root_ptr + 2usize).unwrap()), None);
// The bloom as a pointer:
// - The address at which the data are
let bloom_ptr =
vm.get_maybe(&(header_ptr + 13usize).unwrap()).unwrap().get_relocatable().unwrap();
// The Bloom data, as felt*
for i in 0..16 {
assert_eq!(
vm.get_maybe(&(bloom_ptr + i as usize).unwrap()),
Some(keth_block.block_header.bloom.data[i].0.clone())
);
}
// After the last Bloom data index, the memory should be None.
assert_eq!(vm.get_maybe(&(bloom_ptr + 16usize).unwrap()), None);
// The difficulty as U256:
// - Low
// - High
assert_eq!(
vm.get_maybe(&(header_ptr + 14usize).unwrap()),
Some(keth_block.block_header.difficulty.low.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 15usize).unwrap()),
Some(keth_block.block_header.difficulty.high.0)
);
// The block number as MaybeRelocatable:
assert_eq!(
vm.get_maybe(&(header_ptr + 16usize).unwrap()),
Some(keth_block.block_header.number.0)
);
// The gas limit as MaybeRelocatable:
assert_eq!(
vm.get_maybe(&(header_ptr + 17usize).unwrap()),
Some(keth_block.block_header.gas_limit.0)
);
// The gas used as MaybeRelocatable:
assert_eq!(
vm.get_maybe(&(header_ptr + 18usize).unwrap()),
Some(keth_block.block_header.gas_used.0)
);
// The timestamp as MaybeRelocatable:
assert_eq!(
vm.get_maybe(&(header_ptr + 19usize).unwrap()),
Some(keth_block.block_header.timestamp.0)
);
// The mix hash as U256:
// - Low
// - High
assert_eq!(
vm.get_maybe(&(header_ptr + 20usize).unwrap()),
Some(keth_block.block_header.mix_hash.low.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 21usize).unwrap()),
Some(keth_block.block_header.mix_hash.high.0)
);
// The nonce as MaybeRelocatable:
assert_eq!(
vm.get_maybe(&(header_ptr + 22usize).unwrap()),
Some(keth_block.block_header.nonce.0)
);
// The base fee per gas as an Option of MaybeRelocatable:
// - is_some
// - Value
assert_eq!(
vm.get_maybe(&(header_ptr + 23usize).unwrap()),
Some(keth_block.block_header.base_fee_per_gas.is_some.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 24usize).unwrap()),
Some(keth_block.block_header.base_fee_per_gas.value.0)
);
// The blob gas used as an Option of MaybeRelocatable:
// - is_some
// - Value
assert_eq!(
vm.get_maybe(&(header_ptr + 25usize).unwrap()),
Some(keth_block.block_header.blob_gas_used.is_some.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 26usize).unwrap()),
Some(keth_block.block_header.blob_gas_used.value.0)
);
// The excess blob gas as an Option of MaybeRelocatable:
// - is_some
// - Value
assert_eq!(
vm.get_maybe(&(header_ptr + 27usize).unwrap()),
Some(keth_block.block_header.excess_blob_gas.is_some.0)
);
assert_eq!(
vm.get_maybe(&(header_ptr + 28usize).unwrap()),
Some(keth_block.block_header.excess_blob_gas.value.0)
);
// The parent beacon block root as an Option of U256*:
// - is_some
// - address of the U256
assert_eq!(
vm.get_maybe(&(header_ptr + 29usize).unwrap()),
Some(keth_block.block_header.parent_beacon_block_root.is_some.0)
);
let parent_beacon_block_root_ptr =
vm.get_maybe(&(header_ptr + 30usize).unwrap()).unwrap().get_relocatable().unwrap();
// Parent Beacon Block Root U256 pointer:
// - Low
// - High
assert_eq!(
vm.get_maybe(&parent_beacon_block_root_ptr),
Some(keth_block.block_header.parent_beacon_block_root.value.data[0].0.clone())
);
assert_eq!(
vm.get_maybe(&(parent_beacon_block_root_ptr + 1usize).unwrap()),
Some(keth_block.block_header.parent_beacon_block_root.value.data[1].0.clone())
);
assert_eq!(vm.get_maybe(&(parent_beacon_block_root_ptr + 2usize).unwrap()), None);
// The requests root as an Option of U256*:
// - is_some
// - address of the U256
assert_eq!(
vm.get_maybe(&(header_ptr + 31usize).unwrap()),
Some(keth_block.block_header.requests_root.is_some.0)
);
let requests_root_ptr =
vm.get_maybe(&(header_ptr + 32usize).unwrap()).unwrap().get_relocatable().unwrap();
// Requests Root U256 pointer (None in this case):
// - Low
// - High
assert_eq!(vm.get_maybe(&requests_root_ptr), None);
// The extra data pointer as KethPointer:
// - Length
// - Address
assert_eq!(
vm.get_maybe(&(header_ptr + 33usize).unwrap()),
Some(keth_block.block_header.extra_data.len.0)
);
let extra_data_ptr =
vm.get_maybe(&(header_ptr + 34usize).unwrap()).unwrap().get_relocatable().unwrap();
// The Extra Data, as felt*, should be stored in the second segment of the memory.
assert_eq!(
vm.get_maybe(&extra_data_ptr),
Some(keth_block.block_header.extra_data.data[0].0.clone())
);
// After the last Extra Data index, the memory should be None.
assert_eq!(vm.get_maybe(&(extra_data_ptr + 1usize).unwrap()), None);
// End of the header
assert_eq!(vm.get_maybe(&(header_ptr + 35usize).unwrap()), None);
// First transaction
// Rlp of the transaction as a KethPointer:
// - Length
// - Address
assert_eq!(
vm.get_maybe(&transaction_ptr),
Some(keth_block.transactions[0].rlp.len.0.clone())
);
let transaction1_rlp_ptr =
vm.get_maybe(&(transaction_ptr + 1usize).unwrap()).unwrap().get_relocatable().unwrap();
// The first transaction rlp, as felt*
for i in 0..128 {
assert_eq!(
vm.get_maybe(&(transaction1_rlp_ptr + i as usize).unwrap()),
Some(keth_block.transactions[0].rlp.data[i].0.clone())
);
}
// After the last transaction rlp index, the memory should be None.
assert_eq!(vm.get_maybe(&(transaction1_rlp_ptr + 128usize).unwrap()), None);
// Transaction signature as a KethPointer:
// - Length
// - Address
assert_eq!(
vm.get_maybe(&(transaction_ptr + 2usize).unwrap()),
Some(keth_block.transactions[0].signature.len.0.clone())
);
let transaction1_signature_ptr =
vm.get_maybe(&(transaction_ptr + 3usize).unwrap()).unwrap().get_relocatable().unwrap();
// The first transaction signature, as felt*
for i in 0..5 {
assert_eq!(
vm.get_maybe(&(transaction1_signature_ptr + i as usize).unwrap()),
Some(keth_block.transactions[0].signature.data[i].0.clone())
);
}
// After the last transaction signature index, the memory should be None.
assert_eq!(vm.get_maybe(&(transaction1_signature_ptr + 5usize).unwrap()), None);
// Transaction sender as an address:
assert_eq!(
vm.get_maybe(&(transaction_ptr + 4usize).unwrap()),
Some(keth_block.transactions[0].sender.0.clone())
);
// Second transaction
// Rlp of the transaction as a KethPointer:
// - Length
// - Address
assert_eq!(
vm.get_maybe(&(transaction_ptr + 5usize).unwrap()),
Some(keth_block.transactions[1].rlp.len.0.clone())
);
let transaction2_rlp_ptr =
vm.get_maybe(&(transaction_ptr + 6usize).unwrap()).unwrap().get_relocatable().unwrap();
// The second transaction rlp, as felt*
for i in 0..128 {
assert_eq!(
vm.get_maybe(&(transaction2_rlp_ptr + i as usize).unwrap()),
Some(keth_block.transactions[0].rlp.data[i].0.clone())
);
}
// After the last transaction rlp index, the memory should be None.
assert_eq!(vm.get_maybe(&(transaction2_rlp_ptr + 128usize).unwrap()), None);
// Transaction signature as a KethPointer:
// - Length
// - Address
assert_eq!(
vm.get_maybe(&(transaction_ptr + 7usize).unwrap()),
Some(keth_block.transactions[1].signature.len.0.clone())
);
let transaction2_signature_ptr =
vm.get_maybe(&(transaction_ptr + 8usize).unwrap()).unwrap().get_relocatable().unwrap();
// The first transaction signature, as felt*
for i in 0..5 {
assert_eq!(
vm.get_maybe(&(transaction2_signature_ptr + i as usize).unwrap()),
Some(keth_block.transactions[0].signature.data[i].0.clone())
);
}
// After the last transaction signature index, the memory should be None.
assert_eq!(vm.get_maybe(&(transaction2_signature_ptr + 5usize).unwrap()), None);
// Transaction sender as an address:
assert_eq!(
vm.get_maybe(&(transaction_ptr + 9usize).unwrap()),
Some(keth_block.transactions[1].sender.0.clone())
);
// End of the transactions
assert_eq!(vm.get_maybe(&(transaction_ptr + 10usize).unwrap()), None);
}

Now that this check is done, it would be beneficial to add another test below with an arbitrary block in order to add an even larger and arbitrary test coverage while keeping the harcoded test which will serve as a reference for the implementation and for us in the future (as the test is simplified, it is easy to navigate and understand if there is a problem).

cc @varun-doshi maybe you could be interested by this one

@tcoratger tcoratger added the good first issue Good for newcomers label Nov 30, 2024
@github-project-automation github-project-automation bot moved this to Backlog in Keth Nov 30, 2024
@varun-doshi
Copy link

Yes I can take this up

@tcoratger
Copy link
Collaborator Author

Yes I can take this up

Perfect, assigned

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
Status: Backlog
Development

No branches or pull requests

3 participants