2023-09-26 11:13:57 -04:00
use anyhow ::{ anyhow , Result } ;
2023-05-04 09:57:02 +02:00
use ethereum_types ::{ Address , U256 } ;
use hex_literal ::hex ;
use keccak_hash ::keccak ;
use rand ::{ thread_rng , Rng } ;
use crate ::cpu ::kernel ::aggregator ::KERNEL ;
use crate ::cpu ::kernel ::constants ::global_metadata ::GlobalMetadata ;
use crate ::cpu ::kernel ::constants ::txn_fields ::NormalizedTxnField ;
use crate ::cpu ::kernel ::interpreter ::Interpreter ;
use crate ::generation ::mpt ::{ all_mpt_prover_inputs_reversed , LegacyReceiptRlp , LogRlp } ;
use crate ::memory ::segments ::Segment ;
#[ test ]
fn test_process_receipt ( ) -> Result < ( ) > {
/* Tests process_receipt, which:
- computes the cumulative gas
- computes the bloom filter
- inserts the receipt data in MPT_TRIE_DATA
- inserts a node in receipt_trie
- resets the bloom filter to 0 for the next transaction . * /
let process_receipt = KERNEL . global_labels [ " process_receipt " ] ;
let success = U256 ::from ( 1 ) ;
let leftover_gas = U256 ::from ( 4000 ) ;
let prev_cum_gas = U256 ::from ( 1000 ) ;
let retdest = 0xDEADBEEF u32 . into ( ) ;
// Log.
let address : Address = thread_rng ( ) . gen ( ) ;
let num_topics = 1 ;
let mut topic = vec! [ 0_ u8 ; 32 ] ;
topic [ 31 ] = 4 ;
// Compute the expected Bloom filter.
let test_logs_list = vec! [ ( address . to_fixed_bytes ( ) . to_vec ( ) , vec! [ topic ] ) ] ;
let expected_bloom = logs_bloom_bytes_fn ( test_logs_list ) . to_vec ( ) ;
// Set memory.
2023-09-27 16:00:16 +02:00
let num_nibbles = 2. into ( ) ;
let initial_stack : Vec < U256 > = vec! [
retdest ,
num_nibbles ,
0. into ( ) ,
prev_cum_gas ,
leftover_gas ,
success ,
] ;
2023-05-04 09:57:02 +02:00
let mut interpreter = Interpreter ::new_with_kernel ( process_receipt , initial_stack ) ;
interpreter . set_memory_segment (
Segment ::LogsData ,
vec! [
56. into ( ) , // payload len
U256 ::from_big_endian ( & address . to_fixed_bytes ( ) ) , // address
num_topics . into ( ) , // num_topics
4. into ( ) , // topic
0. into ( ) , // data_len
] ,
) ;
interpreter . set_txn_field ( NormalizedTxnField ::GasLimit , U256 ::from ( 5000 ) ) ;
interpreter . set_memory_segment ( Segment ::TxnBloom , vec! [ 0. into ( ) ; 256 ] ) ;
interpreter . set_memory_segment ( Segment ::BlockBloom , vec! [ 0. into ( ) ; 256 ] ) ;
interpreter . set_memory_segment ( Segment ::Logs , vec! [ 0. into ( ) ] ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::LogsPayloadLen , 58. into ( ) ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::LogsLen , U256 ::from ( 1 ) ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::ReceiptTrieRoot , 500. into ( ) ) ;
interpreter . run ( ) ? ;
let segment_read = interpreter . get_memory_segment ( Segment ::TrieData ) ;
// The expected TrieData has the form [payload_len, status, cum_gas_used, bloom_filter, logs_payload_len, num_logs, [logs]]
let mut expected_trie_data : Vec < U256 > = vec! [ 323. into ( ) , success , 2000. into ( ) ] ;
expected_trie_data . extend (
expected_bloom
. into_iter ( )
. map ( | elt | elt . into ( ) )
. collect ::< Vec < U256 > > ( ) ,
) ;
expected_trie_data . push ( 58. into ( ) ) ; // logs_payload_len
expected_trie_data . push ( 1. into ( ) ) ; // num_logs
expected_trie_data . extend ( vec! [
56. into ( ) , // payload len
U256 ::from_big_endian ( & address . to_fixed_bytes ( ) ) , // address
num_topics . into ( ) , // num_topics
4. into ( ) , // topic
0. into ( ) , // data_len
] ) ;
assert_eq! (
expected_trie_data ,
segment_read [ 0 .. expected_trie_data . len ( ) ]
) ;
Ok ( ( ) )
}
/// Values taken from the block 1000000 of Goerli: https://goerli.etherscan.io/txs?block=1000000
#[ test ]
fn test_receipt_encoding ( ) -> Result < ( ) > {
// Initialize interpreter.
let success = U256 ::from ( 1 ) ;
let retdest = 0xDEADBEEF u32 . into ( ) ;
let num_topics = 3 ;
let encode_receipt = KERNEL . global_labels [ " encode_receipt " ] ;
// Logs and receipt in encodable form.
let log_1 = LogRlp {
address : hex ! ( " 7ef66b77759e12Caf3dDB3E4AFF524E577C59D8D " ) . into ( ) ,
topics : vec ! [
hex! ( " 8a22ee899102a366ac8ad0495127319cb1ff2403cfae855f83a89cda1266674d " ) . into ( ) ,
hex! ( " 0000000000000000000000000000000000000000000000000000000000000004 " ) . into ( ) ,
hex! ( " 00000000000000000000000000000000000000000000000000000000004920ea " ) . into ( ) ,
] ,
data : hex ! ( " a814f7df6a2203dc0e472e8828be95957c6b329fee8e2b1bb6f044c1eb4fc243 " )
. to_vec ( )
. into ( ) ,
} ;
let receipt_1 = LegacyReceiptRlp {
status : true ,
cum_gas_used : 0x02dcb6 u64 . into ( ) ,
bloom : hex ! ( " 00000000000000000000000000000000000000000000000000800000000000000040000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000008000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000400000000000000000000000000000002000040000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000008000000000000000000000000 " ) . to_vec ( ) . into ( ) ,
logs : vec ! [ log_1 ] ,
} ;
// Get the expected RLP encoding.
let expected_rlp = rlp ::encode ( & rlp ::encode ( & receipt_1 ) ) ;
2023-09-27 16:00:16 +02:00
let initial_stack : Vec < U256 > = vec! [ retdest , 0. into ( ) , 0. into ( ) ] ;
2023-05-04 09:57:02 +02:00
let mut interpreter = Interpreter ::new_with_kernel ( encode_receipt , initial_stack ) ;
// Write data to memory.
let expected_bloom_bytes = vec! [
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 0x80 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x40 , 00 , 00 , 00 , 00 , 0x10 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x02 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x08 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 0x01 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x01 , 00 , 00 , 00 , 0x40 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x20 , 00 , 0x04 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x80 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x08 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
] ;
let expected_bloom : Vec < U256 > = expected_bloom_bytes
. into_iter ( )
. map ( | elt | elt . into ( ) )
. collect ( ) ;
let addr = U256 ::from ( [
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x7e , 0xf6 , 0x6b , 0x77 , 0x75 , 0x9e , 0x12 , 0xca , 0xf3 ,
0xdd , 0xb3 , 0xe4 , 0xaf , 0xf5 , 0x24 , 0xe5 , 0x77 , 0xc5 , 0x9d , 0x8d ,
] ) ;
let topic1 = U256 ::from ( [
0x8a , 0x22 , 0xee , 0x89 , 0x91 , 0x02 , 0xa3 , 0x66 , 0xac , 0x8a , 0xd0 , 0x49 , 0x51 , 0x27 , 0x31 ,
0x9c , 0xb1 , 0xff , 0x24 , 0x03 , 0xcf , 0xae , 0x85 , 0x5f , 0x83 , 0xa8 , 0x9c , 0xda , 0x12 , 0x66 ,
0x67 , 0x4d ,
] ) ;
let topic2 = 4. into ( ) ;
let topic3 = 0x4920ea . into ( ) ;
let mut logs = vec! [
155. into ( ) , // unused
addr ,
num_topics . into ( ) , // num_topics
topic1 , // topic1
topic2 , // topic2
topic3 , // topic3
32. into ( ) , // data length
] ;
let cur_data = hex! ( " a814f7df6a2203dc0e472e8828be95957c6b329fee8e2b1bb6f044c1eb4fc243 " )
. iter ( )
. copied ( )
. map ( U256 ::from ) ;
logs . extend ( cur_data ) ;
let mut receipt = vec! [ 423. into ( ) , success , receipt_1 . cum_gas_used ] ;
receipt . extend ( expected_bloom . clone ( ) ) ;
receipt . push ( 157. into ( ) ) ; // logs_payload_len
receipt . push ( 1. into ( ) ) ; // num_logs
receipt . extend ( logs . clone ( ) ) ;
interpreter . set_memory_segment ( Segment ::LogsData , logs ) ;
interpreter . set_memory_segment ( Segment ::TxnBloom , expected_bloom ) ;
interpreter . set_memory_segment ( Segment ::Logs , vec! [ 0. into ( ) ] ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::LogsLen , 1. into ( ) ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::LogsPayloadLen , 157. into ( ) ) ;
interpreter . set_memory_segment ( Segment ::TrieData , receipt ) ;
interpreter . run ( ) ? ;
let rlp_pos = interpreter . pop ( ) ;
let rlp_read : Vec < u8 > = interpreter . get_rlp_memory ( ) ;
assert_eq! ( rlp_pos . as_usize ( ) , expected_rlp . len ( ) ) ;
for i in 0 .. rlp_read . len ( ) {
assert_eq! ( rlp_read [ i ] , expected_rlp [ i ] ) ;
}
Ok ( ( ) )
}
/// Values taken from the block 1000000 of Goerli: https://goerli.etherscan.io/txs?block=1000000
#[ test ]
fn test_receipt_bloom_filter ( ) -> Result < ( ) > {
let logs_bloom = KERNEL . global_labels [ " logs_bloom " ] ;
let num_topics = 3 ;
// Expected bloom
let first_bloom_bytes = vec! [
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 0x80 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x40 , 00 , 00 , 00 , 00 , 0x50 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x02 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x08 , 00 , 0x08 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x50 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x10 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x20 , 00 , 00 , 00 , 00 , 00 , 0x08 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
] ;
let retdest = 0xDEADBEEF u32 . into ( ) ;
let addr = U256 ::from ( [
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x7e , 0xf6 , 0x6b , 0x77 , 0x75 , 0x9e , 0x12 , 0xca , 0xf3 ,
0xdd , 0xb3 , 0xe4 , 0xaf , 0xf5 , 0x24 , 0xe5 , 0x77 , 0xc5 , 0x9d , 0x8d ,
] ) ;
let topic1 = U256 ::from ( [
0x8a , 0x22 , 0xee , 0x89 , 0x91 , 0x02 , 0xa3 , 0x66 , 0xac , 0x8a , 0xd0 , 0x49 , 0x51 , 0x27 , 0x31 ,
0x9c , 0xb1 , 0xff , 0x24 , 0x03 , 0xcf , 0xae , 0x85 , 0x5f , 0x83 , 0xa8 , 0x9c , 0xda , 0x12 , 0x66 ,
0x67 , 0x4d ,
] ) ;
let topic02 = 0x2a . into ( ) ;
let topic03 = 0xbd9fe6 . into ( ) ;
// Set logs memory and initialize TxnBloom and BlockBloom segments.
2023-09-27 16:00:16 +02:00
let initial_stack : Vec < U256 > = vec! [ retdest ] ;
2023-05-04 09:57:02 +02:00
let mut interpreter = Interpreter ::new_with_kernel ( logs_bloom , initial_stack ) ;
let mut logs = vec! [
0. into ( ) , // unused
addr ,
num_topics . into ( ) , // num_topics
topic1 , // topic1
topic02 , // topic2
topic03 , // topic3
32. into ( ) , // data_len
] ;
let cur_data = hex! ( " a814f7df6a2203dc0e472e8828be95957c6b329fee8e2b1bb6f044c1eb4fc243 " )
. iter ( )
. copied ( )
. map ( U256 ::from ) ;
logs . extend ( cur_data ) ;
// The Bloom filter initialization is required for this test to ensure we have the correct length for the filters. Otherwise, some trailing zeroes could be missing.
interpreter . set_memory_segment ( Segment ::TxnBloom , vec! [ 0. into ( ) ; 256 ] ) ; // Initialize transaction Bloom filter.
interpreter . set_memory_segment ( Segment ::BlockBloom , vec! [ 0. into ( ) ; 256 ] ) ; // Initialize block Bloom filter.
interpreter . set_memory_segment ( Segment ::LogsData , logs ) ;
interpreter . set_memory_segment ( Segment ::Logs , vec! [ 0. into ( ) ] ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::LogsLen , U256 ::from ( 1 ) ) ;
interpreter . run ( ) ? ;
// Second transaction.
let loaded_bloom_u256 = interpreter . get_memory_segment ( Segment ::TxnBloom ) ;
let loaded_bloom : Vec < u8 > = loaded_bloom_u256
. into_iter ( )
. map ( | elt | elt . 0 [ 0 ] as u8 )
. collect ( ) ;
assert_eq! ( first_bloom_bytes , loaded_bloom ) ;
let topic12 = 0x4 . into ( ) ;
let topic13 = 0x4920ea . into ( ) ;
let mut logs2 = vec! [
0. into ( ) , // unused
addr ,
num_topics . into ( ) , // num_topics
topic1 , // topic1
topic12 , // topic2
topic13 , // topic3
32. into ( ) , // data_len
] ;
let cur_data = hex! ( " a814f7df6a2203dc0e472e8828be95957c6b329fee8e2b1bb6f044c1eb4fc243 " )
. iter ( )
. copied ( )
. map ( U256 ::from ) ;
logs2 . extend ( cur_data ) ;
interpreter . push ( retdest ) ;
interpreter . generation_state . registers . program_counter = logs_bloom ;
interpreter . set_memory_segment ( Segment ::TxnBloom , vec! [ 0. into ( ) ; 256 ] ) ; // Initialize transaction Bloom filter.
interpreter . set_memory_segment ( Segment ::LogsData , logs2 ) ;
interpreter . set_memory_segment ( Segment ::Logs , vec! [ 0. into ( ) ] ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::LogsLen , U256 ::from ( 1 ) ) ;
interpreter . run ( ) ? ;
let second_bloom_bytes = vec! [
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 0x80 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x40 , 00 , 00 , 00 , 00 , 0x10 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x02 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x08 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 0x01 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x01 , 00 , 00 , 00 , 0x40 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x20 , 00 , 0x04 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x80 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x08 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
] ;
let second_loaded_bloom_u256 = interpreter . get_memory_segment ( Segment ::TxnBloom ) ;
let second_loaded_bloom : Vec < u8 > = second_loaded_bloom_u256
. into_iter ( )
. map ( | elt | elt . 0 [ 0 ] as u8 )
. collect ( ) ;
assert_eq! ( second_bloom_bytes , second_loaded_bloom ) ;
// Check the final block Bloom.
let block_bloom = hex! ( " 00000000000000000000000000000000000000000000000000800000000000000040000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000008000000000000000000000000000000000000000001000000080008000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000500000000000000000000000000000002000040000000000000000000000000000000000000000000000008000000000000000000000100000000000000000000000000020000000000008000000000000000000000000 " ) . to_vec ( ) ;
let loaded_block_bloom : Vec < u8 > = interpreter
. get_memory_segment ( Segment ::BlockBloom )
. into_iter ( )
. map ( | elt | elt . 0 [ 0 ] as u8 )
. collect ( ) ;
assert_eq! ( block_bloom , loaded_block_bloom ) ;
Ok ( ( ) )
}
#[ test ]
fn test_mpt_insert_receipt ( ) -> Result < ( ) > {
// This test simulates a receipt processing to test `mpt_insert_receipt_trie`.
// For this, we need to set the data correctly in memory.
// In TrieData, we need to insert a receipt of the form:
// `[payload_len, status, cum_gas_used, bloom, logs_payload_len, num_logs, [logs]]`.
// We also need to set TrieDataSize correctly.
let retdest = 0xDEADBEEF u32 . into ( ) ;
let trie_inputs = Default ::default ( ) ;
let load_all_mpts = KERNEL . global_labels [ " load_all_mpts " ] ;
let mpt_insert = KERNEL . global_labels [ " mpt_insert_receipt_trie " ] ;
let num_topics = 3 ; // Both transactions have the same number of topics.
let payload_len = 423 ; // Total payload length for each receipt.
let logs_payload_len = 157 ; // Payload length for all logs.
let log_payload_len = 155 ; // Payload length for one log.
let num_logs = 1 ;
// Receipt_0:
let status_0 = 1 ;
let cum_gas_used_0 = 0x016e5b ;
let logs_bloom_0_bytes = vec! [
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 0x80 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x40 , 00 , 00 , 00 , 00 , 0x50 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x02 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x08 , 00 , 0x08 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x50 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x10 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x20 , 00 , 00 , 00 , 00 , 00 , 0x08 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
] ;
// Logs_0:
let logs_bloom_0 : Vec < U256 > = logs_bloom_0_bytes
. into_iter ( )
. map ( | elt | elt . into ( ) )
. collect ( ) ;
let addr = U256 ::from ( [
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x7e , 0xf6 , 0x6b , 0x77 , 0x75 , 0x9e , 0x12 , 0xca , 0xf3 ,
0xdd , 0xb3 , 0xe4 , 0xaf , 0xf5 , 0x24 , 0xe5 , 0x77 , 0xc5 , 0x9d , 0x8d ,
] ) ;
// The first topic is shared by the two transactions.
let topic1 = U256 ::from ( [
0x8a , 0x22 , 0xee , 0x89 , 0x91 , 0x02 , 0xa3 , 0x66 , 0xac , 0x8a , 0xd0 , 0x49 , 0x51 , 0x27 , 0x31 ,
0x9c , 0xb1 , 0xff , 0x24 , 0x03 , 0xcf , 0xae , 0x85 , 0x5f , 0x83 , 0xa8 , 0x9c , 0xda , 0x12 , 0x66 ,
0x67 , 0x4d ,
] ) ;
let topic02 = 0x2a . into ( ) ;
let topic03 = 0xbd9fe6 . into ( ) ;
let mut logs_0 = vec! [
log_payload_len . into ( ) , // payload_len
addr ,
num_topics . into ( ) , // num_topics
topic1 , // topic1
topic02 , // topic2
topic03 , // topic3
32. into ( ) , // data_len
] ;
let cur_data = hex! ( " f7af1cc94b1aef2e0fa15f1b4baefa86eb60e78fa4bd082372a0a446d197fb58 " )
. iter ( )
. copied ( )
. map ( U256 ::from ) ;
logs_0 . extend ( cur_data ) ;
let mut receipt : Vec < U256 > = vec! [ 423. into ( ) , status_0 . into ( ) , cum_gas_used_0 . into ( ) ] ;
receipt . extend ( logs_bloom_0 ) ;
receipt . push ( logs_payload_len . into ( ) ) ; // logs_payload_len
receipt . push ( num_logs . into ( ) ) ; // num_logs
receipt . extend ( logs_0 . clone ( ) ) ;
// First, we load all mpts.
2023-09-27 16:00:16 +02:00
let initial_stack : Vec < U256 > = vec! [ retdest ] ;
2023-05-04 09:57:02 +02:00
let mut interpreter = Interpreter ::new_with_kernel ( load_all_mpts , initial_stack ) ;
2023-09-26 11:13:57 -04:00
interpreter . generation_state . mpt_prover_inputs =
all_mpt_prover_inputs_reversed ( & trie_inputs )
. map_err ( | err | anyhow! ( " Invalid MPT data: {:?} " , err ) ) ? ;
2023-05-04 09:57:02 +02:00
interpreter . run ( ) ? ;
// If TrieData is empty, we need to push 0 because the first value is always 0.
let mut cur_trie_data = interpreter . get_memory_segment ( Segment ::TrieData ) ;
if cur_trie_data . is_empty ( ) {
cur_trie_data . push ( 0. into ( ) ) ;
}
// stack: transaction_nb, value_ptr, retdest
2023-09-27 16:00:16 +02:00
let num_nibbles = 2 ;
let initial_stack : Vec < U256 > = vec! [
retdest ,
cur_trie_data . len ( ) . into ( ) ,
0x80 . into ( ) ,
num_nibbles . into ( ) ,
] ;
2023-05-04 09:57:02 +02:00
for i in 0 .. initial_stack . len ( ) {
interpreter . push ( initial_stack [ i ] ) ;
}
interpreter . generation_state . registers . program_counter = mpt_insert ;
// Set memory.
cur_trie_data . extend ( receipt ) ;
interpreter . set_memory_segment ( Segment ::TrieData , cur_trie_data . clone ( ) ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::TrieDataSize , cur_trie_data . len ( ) . into ( ) ) ;
// First insertion.
interpreter . run ( ) ? ;
// receipt_1:
let status_1 = 1 ;
let cum_gas_used_1 = 0x02dcb6 ;
let logs_bloom_1_bytes = vec! [
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 0x80 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x40 , 00 , 00 , 00 , 00 , 0x10 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x02 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x08 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 0x01 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x01 , 00 , 00 , 00 , 0x40 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x20 , 00 , 0x04 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x80 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 0x08 ,
00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 ,
] ;
// Logs_1:
let logs_bloom_1 : Vec < U256 > = logs_bloom_1_bytes
. into_iter ( )
. map ( | elt | elt . into ( ) )
. collect ( ) ;
let topic12 = 4. into ( ) ;
let topic13 = 0x4920ea . into ( ) ;
let mut logs_1 = vec! [
log_payload_len . into ( ) , // payload length
addr ,
num_topics . into ( ) , // nb topics
topic1 , // topic1
topic12 , // topic2
topic13 , // topic3
32. into ( ) , // data length
] ;
let cur_data = hex! ( " a814f7df6a2203dc0e472e8828be95957c6b329fee8e2b1bb6f044c1eb4fc243 " )
. iter ( )
. copied ( )
. map ( U256 ::from ) ;
logs_1 . extend ( cur_data ) ;
let mut receipt_1 : Vec < U256 > = vec! [ payload_len . into ( ) , status_1 . into ( ) , cum_gas_used_1 . into ( ) ] ;
receipt_1 . extend ( logs_bloom_1 ) ;
receipt_1 . push ( logs_payload_len . into ( ) ) ; // logs payload len
receipt_1 . push ( num_logs . into ( ) ) ; // nb logs
receipt_1 . extend ( logs_1 . clone ( ) ) ;
// Get updated TrieData segment.
cur_trie_data = interpreter . get_memory_segment ( Segment ::TrieData ) ;
2023-09-27 16:00:16 +02:00
let num_nibbles = 2 ;
let initial_stack2 : Vec < U256 > = vec! [
retdest ,
cur_trie_data . len ( ) . into ( ) ,
0x01 . into ( ) ,
num_nibbles . into ( ) ,
] ;
2023-05-04 09:57:02 +02:00
for i in 0 .. initial_stack2 . len ( ) {
interpreter . push ( initial_stack2 [ i ] ) ;
}
cur_trie_data . extend ( receipt_1 ) ;
// Set memory.
interpreter . generation_state . registers . program_counter = mpt_insert ;
interpreter . set_memory_segment ( Segment ::TrieData , cur_trie_data . clone ( ) ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::TrieDataSize , cur_trie_data . len ( ) . into ( ) ) ;
interpreter . run ( ) ? ;
// Finally, check that the hashes correspond.
let mpt_hash_receipt = KERNEL . global_labels [ " mpt_hash_receipt_trie " ] ;
interpreter . generation_state . registers . program_counter = mpt_hash_receipt ;
interpreter . push ( retdest ) ;
interpreter . run ( ) ? ;
assert_eq! (
interpreter . stack ( ) [ 0 ] ,
U256 ::from ( hex! (
" da46cdd329bfedace32da95f2b344d314bc6f55f027d65f9f4ac04ee425e1f98 "
) )
) ;
Ok ( ( ) )
}
#[ test ]
fn test_bloom_two_logs ( ) -> Result < ( ) > {
// Tests the Bloom filter computation with two logs in one transaction.
// address
let to = [
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x09 , 0x5e , 0x7b , 0xae , 0xa6 , 0xa6 , 0xc7 , 0xc4 , 0xc2 ,
0xdf , 0xeb , 0x97 , 0x7e , 0xfa , 0xc3 , 0x26 , 0xaf , 0x55 , 0x2d , 0x87 ,
] ;
let retdest = 0xDEADBEEF u32 . into ( ) ;
let logs_bloom = KERNEL . global_labels [ " logs_bloom " ] ;
2023-09-27 16:00:16 +02:00
let initial_stack : Vec < U256 > = vec! [ retdest ] ;
2023-05-04 09:57:02 +02:00
// Set memory.
let logs = vec! [
0. into ( ) , // unused
to . into ( ) , // address
0. into ( ) , // num_topics
0. into ( ) , // data_len,
0. into ( ) , // unused: rlp
to . into ( ) ,
2. into ( ) , // num_topics
0x62 . into ( ) ,
0x63 . into ( ) ,
5. into ( ) ,
[
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xa1 ,
0xb2 , 0xc3 , 0xd4 , 0xe5 ,
]
. into ( ) ,
] ;
let mut interpreter = Interpreter ::new_with_kernel ( logs_bloom , initial_stack ) ;
interpreter . set_memory_segment ( Segment ::TxnBloom , vec! [ 0. into ( ) ; 256 ] ) ; // Initialize transaction Bloom filter.
interpreter . set_memory_segment ( Segment ::BlockBloom , vec! [ 0. into ( ) ; 256 ] ) ; // Initialize block Bloom filter.
interpreter . set_memory_segment ( Segment ::LogsData , logs ) ;
interpreter . set_memory_segment ( Segment ::Logs , vec! [ 0. into ( ) , 4. into ( ) ] ) ;
interpreter . set_global_metadata_field ( GlobalMetadata ::LogsLen , U256 ::from ( 2 ) ) ;
interpreter . run ( ) ? ;
let loaded_bloom_bytes : Vec < u8 > = interpreter
. get_memory_segment ( Segment ::TxnBloom )
. into_iter ( )
. map ( | elt | elt . 0 [ 0 ] as u8 )
. collect ( ) ;
let expected = hex! ( " 00000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000004000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000400000000000040000000000000000000000000002000000000000000000000000000 " ) . to_vec ( ) ;
assert_eq! ( expected , loaded_bloom_bytes ) ;
Ok ( ( ) )
}
pub fn logs_bloom_bytes_fn ( logs_list : Vec < ( Vec < u8 > , Vec < Vec < u8 > > ) > ) -> [ u8 ; 256 ] {
// The first element of logs_list.
let mut bloom = [ 0_ u8 ; 256 ] ;
for log in logs_list {
let cur_addr = log . 0 ;
let topics = log . 1 ;
add_to_bloom ( & mut bloom , & cur_addr ) ;
for topic in topics {
add_to_bloom ( & mut bloom , & topic ) ;
}
}
bloom
}
fn add_to_bloom ( bloom : & mut [ u8 ; 256 ] , bloom_entry : & [ u8 ] ) {
let bloom_hash = keccak ( bloom_entry ) . to_fixed_bytes ( ) ;
for idx in 0 .. 3 {
let bit_pair = u16 ::from_be_bytes ( bloom_hash [ 2 * idx .. 2 * ( idx + 1 ) ] . try_into ( ) . unwrap ( ) ) ;
let bit_to_set = 0x07FF - ( bit_pair & 0x07FF ) ;
let byte_index = bit_to_set / 8 ;
let bit_value = 1 < < ( 7 - bit_to_set % 8 ) ;
bloom [ byte_index as usize ] | = bit_value ;
}
}