|
| 1 | +use alloy_primitives::{Address, B128, B256, U256}; |
| 2 | +use banderwagon::Fr; |
| 3 | + |
| 4 | +use crate::{ |
| 5 | + committer::DEFAULT_COMMITER, |
| 6 | + constants::{ |
| 7 | + BALANCE_LEAF_KEY, CODE_KECCAK_LEAF_KEY, CODE_OFFSET, CODE_SIZE_LEAF_KEY, |
| 8 | + HEADER_STORAGE_OFFSET, MAIN_STORAGE_OFFSET, NONCE_LEAF_KEY, VERKLE_NODE_WIDTH_U256, |
| 9 | + VERSION_LEAF_KEY, |
| 10 | + }, |
| 11 | + stem::Stem, |
| 12 | + utils::fr_to_b256, |
| 13 | + TrieKey, TrieValue, |
| 14 | +}; |
| 15 | + |
| 16 | +pub struct AccountStorageLayout { |
| 17 | + pub address: Address, |
| 18 | + base_storage_stem: Stem, |
| 19 | +} |
| 20 | + |
| 21 | +impl AccountStorageLayout { |
| 22 | + pub fn new(address: Address) -> Self { |
| 23 | + Self { |
| 24 | + address, |
| 25 | + base_storage_stem: tree_key(address, U256::ZERO, 0).into(), |
| 26 | + } |
| 27 | + } |
| 28 | + |
| 29 | + pub fn version_key(&self) -> TrieKey { |
| 30 | + TrieKey::from_stem_and_last_byte(&self.base_storage_stem, VERSION_LEAF_KEY) |
| 31 | + } |
| 32 | + |
| 33 | + pub fn balance_key(&self) -> TrieKey { |
| 34 | + TrieKey::from_stem_and_last_byte(&self.base_storage_stem, BALANCE_LEAF_KEY) |
| 35 | + } |
| 36 | + |
| 37 | + pub fn nonce_key(&self) -> TrieKey { |
| 38 | + TrieKey::from_stem_and_last_byte(&self.base_storage_stem, NONCE_LEAF_KEY) |
| 39 | + } |
| 40 | + |
| 41 | + pub fn code_hash_key(&self) -> TrieKey { |
| 42 | + TrieKey::from_stem_and_last_byte(&self.base_storage_stem, CODE_KECCAK_LEAF_KEY) |
| 43 | + } |
| 44 | + |
| 45 | + pub fn code_size_key(&self) -> TrieKey { |
| 46 | + TrieKey::from_stem_and_last_byte(&self.base_storage_stem, CODE_SIZE_LEAF_KEY) |
| 47 | + } |
| 48 | + |
| 49 | + pub fn storage_slot_key(&self, storage_key: U256) -> TrieKey { |
| 50 | + let pos = if storage_key < CODE_OFFSET - HEADER_STORAGE_OFFSET { |
| 51 | + HEADER_STORAGE_OFFSET + storage_key |
| 52 | + } else { |
| 53 | + MAIN_STORAGE_OFFSET + storage_key |
| 54 | + }; |
| 55 | + tree_key( |
| 56 | + self.address, |
| 57 | + pos / VERKLE_NODE_WIDTH_U256, |
| 58 | + (pos % VERKLE_NODE_WIDTH_U256).byte(0), |
| 59 | + ) |
| 60 | + } |
| 61 | + |
| 62 | + pub fn code_key(&self, chunk_id: usize) -> TrieKey { |
| 63 | + let pos = CODE_OFFSET + U256::from(chunk_id); |
| 64 | + tree_key( |
| 65 | + self.address, |
| 66 | + pos / VERKLE_NODE_WIDTH_U256, |
| 67 | + (pos % VERKLE_NODE_WIDTH_U256).byte(0), |
| 68 | + ) |
| 69 | + } |
| 70 | + |
| 71 | + pub fn chunkify_code(&self, code: &[u8]) -> Vec<(TrieKey, TrieValue)> { |
| 72 | + const PUSH_OFFSET: u8 = 95; |
| 73 | + const PUSH1: u8 = PUSH_OFFSET + 1; |
| 74 | + const PUSH32: u8 = PUSH_OFFSET + 32; |
| 75 | + |
| 76 | + let mut remaining_push_data = 0u8; |
| 77 | + let mut result = vec![]; |
| 78 | + for (chunk_id, chunk) in code.chunks(31).enumerate() { |
| 79 | + let mut value = Vec::with_capacity(32); |
| 80 | + value.push(remaining_push_data.min(31)); |
| 81 | + value.extend(chunk); |
| 82 | + value.resize(32, 0); |
| 83 | + result.push((self.code_key(chunk_id), TrieValue::from_le_slice(&value))); |
| 84 | + |
| 85 | + for chunk_byte in chunk { |
| 86 | + if remaining_push_data > 0 { |
| 87 | + remaining_push_data -= 1; |
| 88 | + } else if (PUSH1..=PUSH32).contains(chunk_byte) { |
| 89 | + remaining_push_data = chunk_byte - PUSH_OFFSET; |
| 90 | + } |
| 91 | + } |
| 92 | + } |
| 93 | + result |
| 94 | + } |
| 95 | +} |
| 96 | + |
| 97 | +fn tree_key(address: Address, tree_index: U256, sub_index: u8) -> TrieKey { |
| 98 | + let address_bytes = *B256::left_padding_from(address.as_slice()); |
| 99 | + let tree_index_bytes = tree_index.to_le_bytes::<32>(); |
| 100 | + |
| 101 | + let scalars = [ |
| 102 | + 2u128 + 256 * 64, |
| 103 | + u128::from_le_bytes(B128::from_slice(&address_bytes[..16]).0), |
| 104 | + u128::from_le_bytes(B128::from_slice(&address_bytes[16..]).0), |
| 105 | + u128::from_le_bytes(B128::from_slice(&tree_index_bytes[..16]).0), |
| 106 | + u128::from_le_bytes(B128::from_slice(&tree_index_bytes[16..]).0), |
| 107 | + ] |
| 108 | + .map(Fr::from); |
| 109 | + let commitment = DEFAULT_COMMITER.commit_lagrange(&scalars); |
| 110 | + let hash_commitment = commitment.map_to_scalar_field(); |
| 111 | + |
| 112 | + let mut key = fr_to_b256(&hash_commitment); |
| 113 | + key[31] = sub_index; |
| 114 | + key.into() |
| 115 | +} |
0 commit comments