mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 14:23:07 +00:00
merge
This commit is contained in:
commit
c3a5fd8631
@ -35,6 +35,7 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
include_str!("asm/core/terminate.asm"),
|
||||
include_str!("asm/core/transfer.asm"),
|
||||
include_str!("asm/core/util.asm"),
|
||||
include_str!("asm/core/access_lists.asm"),
|
||||
include_str!("asm/curve/bls381/util.asm"),
|
||||
include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"),
|
||||
include_str!("asm/curve/bn254/curve_arithmetic/curve_add.asm"),
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
global sys_extcodehash:
|
||||
// stack: kexit_info, address
|
||||
// TODO: Charge gas.
|
||||
SWAP1
|
||||
SWAP1 %u256_to_addr
|
||||
// stack: address, kexit_info
|
||||
DUP1 %insert_accessed_addresses
|
||||
// stack: cold_access, address, kexit_info
|
||||
PUSH @GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS
|
||||
MUL
|
||||
PUSH @GAS_WARMACCESS
|
||||
ADD
|
||||
%stack (gas, address, kexit_info) -> (gas, kexit_info, address)
|
||||
%charge_gas
|
||||
// stack: kexit_info, address
|
||||
|
||||
SWAP1
|
||||
%extcodehash
|
||||
// stack: hash, kexit_info
|
||||
SWAP1
|
||||
@ -41,7 +51,18 @@ retzero:
|
||||
|
||||
global sys_extcodesize:
|
||||
// stack: kexit_info, address
|
||||
// TODO: Charge gas.
|
||||
SWAP1 %u256_to_addr
|
||||
// stack: address, kexit_info
|
||||
DUP1 %insert_accessed_addresses
|
||||
// stack: cold_access, address, kexit_info
|
||||
PUSH @GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS
|
||||
MUL
|
||||
PUSH @GAS_WARMACCESS
|
||||
ADD
|
||||
%stack (gas, address, kexit_info) -> (gas, kexit_info, address)
|
||||
%charge_gas
|
||||
// stack: kexit_info, address
|
||||
|
||||
SWAP1
|
||||
// stack: address, kexit_info
|
||||
%extcodesize
|
||||
@ -69,6 +90,7 @@ global sys_extcodecopy:
|
||||
// TODO: Charge other gas.
|
||||
%stack (kexit_info, address, dest_offset, offset, size)
|
||||
-> (address, dest_offset, offset, size, kexit_info)
|
||||
%u256_to_addr DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation.
|
||||
%extcodecopy
|
||||
// stack: kexit_info
|
||||
EXIT_KERNEL
|
||||
|
||||
@ -1,7 +1,17 @@
|
||||
global sys_balance:
|
||||
// stack: kexit_info, address
|
||||
// TODO: assuming a cold account access for now.
|
||||
%charge_gas_const(@GAS_COLDACCOUNTACCESS)
|
||||
SWAP1 %u256_to_addr
|
||||
// stack: address, kexit_info
|
||||
DUP1 %insert_accessed_addresses
|
||||
// stack: cold_access, address, kexit_info
|
||||
PUSH @GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS
|
||||
MUL
|
||||
PUSH @GAS_WARMACCESS
|
||||
ADD
|
||||
%stack (gas, address, kexit_info) -> (gas, kexit_info, address)
|
||||
%charge_gas
|
||||
// stack: kexit_info, address
|
||||
|
||||
SWAP1
|
||||
// stack: address, kexit_info
|
||||
%balance
|
||||
|
||||
102
evm/src/cpu/kernel/asm/core/access_lists.asm
Normal file
102
evm/src/cpu/kernel/asm/core/access_lists.asm
Normal file
@ -0,0 +1,102 @@
|
||||
/// Access lists for addresses and storage keys.
|
||||
/// The access list is stored in an array. The length of the array is stored in the global metadata.
|
||||
/// For storage keys, the address and key are stored as two consecutive elements.
|
||||
/// The array is stored in the SEGMENT_ACCESSED_ADDRESSES segment for addresses and in the SEGMENT_ACCESSED_STORAGE_KEYS segment for storage keys.
|
||||
/// Both arrays are stored in the kernel memory (context=0).
|
||||
/// Searching and inserting is done by doing a linear search through the array.
|
||||
/// If the address/storage key isn't found in the array, it is inserted at the end.
|
||||
/// TODO: Look into using a more efficient data structure for the access lists.
|
||||
|
||||
%macro insert_accessed_addresses
|
||||
%stack (addr) -> (addr, %%after)
|
||||
%jump(insert_accessed_addresses)
|
||||
%%after:
|
||||
// stack: cold_access
|
||||
%endmacro
|
||||
|
||||
%macro insert_accessed_addresses_no_return
|
||||
%insert_accessed_addresses
|
||||
POP
|
||||
%endmacro
|
||||
|
||||
/// Inserts the address into the access list if it is not already present.
|
||||
/// Return 1 if the address was inserted, 0 if it was already present.
|
||||
global insert_accessed_addresses:
|
||||
// stack: addr, retdest
|
||||
%mload_global_metadata(@GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN)
|
||||
// stack: len, addr, retdest
|
||||
PUSH 0
|
||||
insert_accessed_addresses_loop:
|
||||
%stack (i, len, addr, retdest) -> (i, len, i, len, addr, retdest)
|
||||
EQ %jumpi(insert_address)
|
||||
// stack: i, len, addr, retdest
|
||||
DUP1 %mload_kernel(@SEGMENT_ACCESSED_ADDRESSES)
|
||||
// stack: loaded_addr, i, len, addr, retdest
|
||||
DUP4
|
||||
// stack: addr, loaded_addr, i, len, addr, retdest
|
||||
EQ %jumpi(insert_accessed_addresses_found)
|
||||
// stack: i, len, addr, retdest
|
||||
%increment
|
||||
%jump(insert_accessed_addresses_loop)
|
||||
|
||||
insert_address:
|
||||
%stack (i, len, addr, retdest) -> (i, addr, len, retdest)
|
||||
%mstore_kernel(@SEGMENT_ACCESSED_ADDRESSES) // Store new address at the end of the array.
|
||||
// stack: len, retdest
|
||||
%increment
|
||||
%mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN) // Store new length.
|
||||
PUSH 1 // Return 1 to indicate that the address was inserted.
|
||||
SWAP1 JUMP
|
||||
|
||||
insert_accessed_addresses_found:
|
||||
%stack (i, len, addr, retdest) -> (retdest, 0) // Return 0 to indicate that the address was already present.
|
||||
JUMP
|
||||
|
||||
|
||||
%macro insert_accessed_storage_keys
|
||||
%stack (addr, key) -> (addr, key, %%after)
|
||||
%jump(insert_accessed_storage_keys)
|
||||
%%after:
|
||||
// stack: cold_access
|
||||
%endmacro
|
||||
|
||||
/// Inserts the storage key into the access list if it is not already present.
|
||||
/// Return 1 if the storage key was inserted, 0 if it was already present.
|
||||
global insert_accessed_storage_keys:
|
||||
// stack: addr, key, retdest
|
||||
%mload_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN)
|
||||
// stack: len, addr, key, retdest
|
||||
PUSH 0
|
||||
insert_accessed_storage_keys_loop:
|
||||
%stack (i, len, addr, key, retdest) -> (i, len, i, len, addr, key, retdest)
|
||||
EQ %jumpi(insert_storage_key)
|
||||
// stack: i, len, addr, key, retdest
|
||||
DUP1 %increment %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
|
||||
// stack: loaded_key, i, len, addr, key, retdest
|
||||
DUP2 %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
|
||||
// stack: loaded_addr, loaded_key, i, len, addr, key, retdest
|
||||
DUP5 EQ
|
||||
// stack: loaded_addr==addr, loaded_key, i, len, addr, key, retdest
|
||||
SWAP1 DUP6 EQ
|
||||
// stack: loaded_key==key, loaded_addr==addr, i, len, addr, key, retdest
|
||||
MUL // AND
|
||||
%jumpi(insert_accessed_storage_keys_found)
|
||||
// stack: i, len, addr, key, retdest
|
||||
%add_const(2)
|
||||
%jump(insert_accessed_storage_keys_loop)
|
||||
|
||||
insert_storage_key:
|
||||
// stack: i, len, addr, key, retdest
|
||||
DUP1 %increment
|
||||
%stack (i_plus_1, i, len, addr, key, retdest) -> (i, addr, i_plus_1, key, i_plus_1, retdest)
|
||||
%mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Store new address at the end of the array.
|
||||
%mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Store new key after that
|
||||
// stack: i_plus_1, retdest
|
||||
%increment
|
||||
%mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) // Store new length in front of the array.
|
||||
PUSH 1 // Return 1 to indicate that the storage key was inserted.
|
||||
SWAP1 JUMP
|
||||
|
||||
insert_accessed_storage_keys_found:
|
||||
%stack (i, len, addr, key, retdest) -> (retdest, 0) // Return 0 to indicate that the storage key was already present.
|
||||
JUMP
|
||||
@ -4,6 +4,12 @@
|
||||
global sys_call:
|
||||
// stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
// TODO: Charge gas.
|
||||
SWAP2
|
||||
// stack: address, gas, kexit_info, value, args_offset, args_size, ret_offset, ret_size
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation.
|
||||
SWAP2
|
||||
// stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
%create_context
|
||||
// stack: new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
|
||||
@ -29,6 +35,12 @@ global sys_call:
|
||||
global sys_callcode:
|
||||
// stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
// TODO: Charge gas.
|
||||
SWAP2
|
||||
// stack: address, gas, kexit_info, value, args_offset, args_size, ret_offset, ret_size
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation.
|
||||
SWAP2
|
||||
// stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
%create_context
|
||||
// stack: new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
|
||||
@ -53,6 +65,12 @@ global sys_callcode:
|
||||
global sys_staticcall:
|
||||
// stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
// TODO: Charge gas.
|
||||
SWAP2
|
||||
// stack: address, gas, kexit_info, args_offset, args_size, ret_offset, ret_size
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation.
|
||||
SWAP2
|
||||
// stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
%create_context
|
||||
// stack: new_ctx, kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
|
||||
@ -74,6 +92,12 @@ global sys_staticcall:
|
||||
global sys_delegatecall:
|
||||
// stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
// TODO: Charge gas.
|
||||
SWAP2
|
||||
// stack: address, gas, kexit_info, args_offset, args_size, ret_offset, ret_size
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation.
|
||||
SWAP2
|
||||
// stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
%create_context
|
||||
// stack: new_ctx, kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
|
||||
|
||||
@ -73,6 +73,7 @@ sys_create2_finish:
|
||||
// Note: CODE_ADDR refers to a (context, segment, offset) tuple.
|
||||
global create_inner:
|
||||
// stack: address, sender, endowment, CODE_ADDR, code_len, retdest
|
||||
DUP1 %insert_accessed_addresses_no_return
|
||||
%stack (address, sender, endowment)
|
||||
-> (sender, address, endowment, sender, address)
|
||||
|
||||
|
||||
@ -81,6 +81,8 @@ global process_contract_creation_txn:
|
||||
// stack: account_ptr, address, retdest
|
||||
DUP2
|
||||
// stack: address, account_ptr, address, retdest
|
||||
%addr_to_state_key
|
||||
// stack: state_key, account_ptr, address, retdest
|
||||
%mpt_insert_state_trie
|
||||
// stack: address, retdest
|
||||
|
||||
@ -127,13 +129,25 @@ global process_message_txn:
|
||||
// stack: retdest
|
||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||
%mload_txn_field(@TXN_FIELD_TO)
|
||||
DUP1 %insert_accessed_addresses_no_return
|
||||
%mload_txn_field(@TXN_FIELD_ORIGIN)
|
||||
DUP1 %insert_accessed_addresses_no_return
|
||||
// stack: from, to, amount, retdest
|
||||
%transfer_eth
|
||||
// stack: transfer_eth_status, retdest
|
||||
%jumpi(process_message_txn_insufficient_balance)
|
||||
// stack: retdest
|
||||
|
||||
// Add precompiles to accessed addresses.
|
||||
PUSH @ECREC %insert_accessed_addresses_no_return
|
||||
PUSH @SHA256 %insert_accessed_addresses_no_return
|
||||
PUSH @RIP160 %insert_accessed_addresses_no_return
|
||||
PUSH @ID %insert_accessed_addresses_no_return
|
||||
PUSH @EXPMOD %insert_accessed_addresses_no_return
|
||||
PUSH @BN_ADD %insert_accessed_addresses_no_return
|
||||
PUSH @BN_MUL %insert_accessed_addresses_no_return
|
||||
PUSH @SNARKV %insert_accessed_addresses_no_return
|
||||
PUSH @BLAKE2_F %insert_accessed_addresses_no_return
|
||||
// TODO: Handle precompiles.
|
||||
|
||||
// If to's code is empty, return.
|
||||
|
||||
@ -19,8 +19,13 @@ global sys_return:
|
||||
%jump(terminate_common)
|
||||
|
||||
global sys_selfdestruct:
|
||||
// stack: kexit_info
|
||||
// stack: kexit_info, address
|
||||
SWAP1 %u256_to_addr
|
||||
DUP1 %insert_accessed_addresses_no_return // TODO: Use return value in gas calculation.
|
||||
// stack: address, kexit_info
|
||||
SWAP1
|
||||
// TODO: Charge gas.
|
||||
// TODO: Add address to the access list.
|
||||
%consume_gas_const(@GAS_SELFDESTRUCT)
|
||||
%leftover_gas
|
||||
// stack: leftover_gas
|
||||
|
||||
@ -5,9 +5,19 @@
|
||||
|
||||
global sys_sload:
|
||||
// stack: kexit_info, slot
|
||||
// TODO: Charge gas.
|
||||
SWAP1
|
||||
// stack: slot, kexit_info
|
||||
DUP1 %address
|
||||
// stack: addr, slot, slot, kexit_info
|
||||
%insert_accessed_storage_keys PUSH @GAS_COLDSLOAD_MINUS_WARMACCESS
|
||||
MUL
|
||||
PUSH @GAS_WARMACCESS
|
||||
ADD
|
||||
%stack (gas, slot, kexit_info) -> (gas, kexit_info, slot)
|
||||
%charge_gas
|
||||
// stack: kexit_info, slot
|
||||
|
||||
SWAP1
|
||||
%stack (slot) -> (slot, after_storage_read)
|
||||
%slot_to_storage_key
|
||||
// stack: storage_key, after_storage_read, kexit_info
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
// Post stack: (empty)
|
||||
|
||||
global sys_sstore:
|
||||
%stack (kexit_info, slot, value) -> (slot, kexit_info, slot, value)
|
||||
%address %insert_accessed_storage_keys POP // TODO: Use return value in gas calculation.
|
||||
// TODO: Assuming a cold zero -> nonzero write for now.
|
||||
PUSH @GAS_COLDSLOAD
|
||||
PUSH @GAS_SSET
|
||||
|
||||
@ -345,3 +345,8 @@
|
||||
%endrep
|
||||
// stack: a || b || c || d
|
||||
%endmacro
|
||||
|
||||
%macro u256_to_addr
|
||||
// stack: x
|
||||
%mod_const(0x10000000000000000000000000000000000000000) // 2^160
|
||||
%endmacro
|
||||
|
||||
@ -45,10 +45,14 @@ pub(crate) enum GlobalMetadata {
|
||||
|
||||
/// Gas to refund at the end of the transaction.
|
||||
RefundCounter = 22,
|
||||
/// Length of the addresses access list.
|
||||
AccessedAddressesLen = 23,
|
||||
/// Length of the storage keys access list.
|
||||
AccessedStorageKeysLen = 24,
|
||||
}
|
||||
|
||||
impl GlobalMetadata {
|
||||
pub(crate) const COUNT: usize = 22;
|
||||
pub(crate) const COUNT: usize = 24;
|
||||
|
||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||
[
|
||||
@ -74,6 +78,8 @@ impl GlobalMetadata {
|
||||
Self::BlockChainId,
|
||||
Self::BlockBaseFee,
|
||||
Self::RefundCounter,
|
||||
Self::AccessedAddressesLen,
|
||||
Self::AccessedStorageKeysLen,
|
||||
]
|
||||
}
|
||||
|
||||
@ -102,6 +108,8 @@ impl GlobalMetadata {
|
||||
Self::BlockChainId => "GLOBAL_METADATA_BLOCK_CHAIN_ID",
|
||||
Self::BlockBaseFee => "GLOBAL_METADATA_BLOCK_BASE_FEE",
|
||||
Self::RefundCounter => "GLOBAL_METADATA_REFUND_COUNTER",
|
||||
Self::AccessedAddressesLen => "GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN",
|
||||
Self::AccessedStorageKeysLen => "GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,10 @@ pub fn evm_constants() -> HashMap<String, U256> {
|
||||
c.insert(name.into(), U256::from(value));
|
||||
}
|
||||
|
||||
for (name, value) in PRECOMPILES {
|
||||
c.insert(name.into(), U256::from(value));
|
||||
}
|
||||
|
||||
for segment in Segment::all() {
|
||||
c.insert(segment.var_name().into(), (segment as u32).into());
|
||||
}
|
||||
@ -151,7 +155,7 @@ const EC_CONSTANTS: [(&str, [u8; 32]); 18] = [
|
||||
),
|
||||
];
|
||||
|
||||
const GAS_CONSTANTS: [(&str, u16); 36] = [
|
||||
const GAS_CONSTANTS: [(&str, u16); 38] = [
|
||||
("GAS_ZERO", 0),
|
||||
("GAS_JUMPDEST", 1),
|
||||
("GAS_BASE", 2),
|
||||
@ -163,7 +167,9 @@ const GAS_CONSTANTS: [(&str, u16); 36] = [
|
||||
("GAS_ACCESSLISTADDRESS", 2_400),
|
||||
("GAS_ACCESSLISTSTORAGE", 1_900),
|
||||
("GAS_COLDACCOUNTACCESS", 2_600),
|
||||
("GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS", 2_500),
|
||||
("GAS_COLDSLOAD", 2_100),
|
||||
("GAS_COLDSLOAD_MINUS_WARMACCESS", 2_000),
|
||||
("GAS_SSET", 20_000),
|
||||
("GAS_SRESET", 2_900),
|
||||
("REFUND_SCLEAR", 15_000),
|
||||
@ -189,3 +195,15 @@ const GAS_CONSTANTS: [(&str, u16); 36] = [
|
||||
("GAS_COPY", 3),
|
||||
("GAS_BLOCKHASH", 20),
|
||||
];
|
||||
|
||||
const PRECOMPILES: [(&str, u16); 9] = [
|
||||
("ECREC", 1),
|
||||
("SHA256", 2),
|
||||
("RIP160", 3),
|
||||
("ID", 4),
|
||||
("EXPMOD", 5),
|
||||
("BN_ADD", 6),
|
||||
("BN_MUL", 7),
|
||||
("SNARKV", 8),
|
||||
("BLAKE2_F", 9),
|
||||
];
|
||||
|
||||
@ -59,6 +59,7 @@ pub fn run_interpreter(
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InterpreterMemoryInitialization {
|
||||
pub label: String,
|
||||
pub stack: Vec<U256>,
|
||||
|
||||
195
evm/src/cpu/kernel/tests/core/access_lists.rs
Normal file
195
evm/src/cpu/kernel/tests/core/access_lists.rs
Normal file
@ -0,0 +1,195 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use anyhow::Result;
|
||||
use ethereum_types::{Address, U256};
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::kernel::constants::global_metadata::GlobalMetadata::{
|
||||
AccessedAddressesLen, AccessedStorageKeysLen,
|
||||
};
|
||||
use crate::cpu::kernel::interpreter::Interpreter;
|
||||
use crate::memory::segments::Segment::{AccessedAddresses, AccessedStorageKeys, GlobalMetadata};
|
||||
use crate::witness::memory::MemoryAddress;
|
||||
|
||||
#[test]
|
||||
fn test_insert_accessed_addresses() -> Result<()> {
|
||||
let insert_accessed_addresses = KERNEL.global_labels["insert_accessed_addresses"];
|
||||
|
||||
let retaddr = 0xdeadbeefu32.into();
|
||||
let mut rng = thread_rng();
|
||||
let n = rng.gen_range(1..10);
|
||||
let addresses = (0..n)
|
||||
.map(|_| rng.gen::<Address>())
|
||||
.collect::<HashSet<_>>()
|
||||
.into_iter()
|
||||
.collect::<Vec<Address>>();
|
||||
let addr_in_list = addresses[rng.gen_range(0..n)];
|
||||
let addr_not_in_list = rng.gen::<Address>();
|
||||
assert!(
|
||||
!addresses.contains(&addr_not_in_list),
|
||||
"Cosmic luck or bad RNG?"
|
||||
);
|
||||
|
||||
// Test for address already in list.
|
||||
let initial_stack = vec![retaddr, U256::from(addr_in_list.0.as_slice())];
|
||||
let mut interpreter = Interpreter::new_with_kernel(insert_accessed_addresses, initial_stack);
|
||||
for i in 0..n {
|
||||
let addr = U256::from(addresses[i].0.as_slice());
|
||||
interpreter
|
||||
.generation_state
|
||||
.memory
|
||||
.set(MemoryAddress::new(0, AccessedAddresses, i), addr);
|
||||
}
|
||||
interpreter.generation_state.memory.set(
|
||||
MemoryAddress::new(0, GlobalMetadata, AccessedAddressesLen as usize),
|
||||
U256::from(n),
|
||||
);
|
||||
interpreter.run()?;
|
||||
assert_eq!(interpreter.stack(), &[U256::zero()]);
|
||||
assert_eq!(
|
||||
interpreter.generation_state.memory.get(MemoryAddress::new(
|
||||
0,
|
||||
GlobalMetadata,
|
||||
AccessedAddressesLen as usize
|
||||
)),
|
||||
U256::from(n)
|
||||
);
|
||||
|
||||
// Test for address not in list.
|
||||
let initial_stack = vec![retaddr, U256::from(addr_not_in_list.0.as_slice())];
|
||||
let mut interpreter = Interpreter::new_with_kernel(insert_accessed_addresses, initial_stack);
|
||||
for i in 0..n {
|
||||
let addr = U256::from(addresses[i].0.as_slice());
|
||||
interpreter
|
||||
.generation_state
|
||||
.memory
|
||||
.set(MemoryAddress::new(0, AccessedAddresses, i), addr);
|
||||
}
|
||||
interpreter.generation_state.memory.set(
|
||||
MemoryAddress::new(0, GlobalMetadata, AccessedAddressesLen as usize),
|
||||
U256::from(n),
|
||||
);
|
||||
interpreter.run()?;
|
||||
assert_eq!(interpreter.stack(), &[U256::one()]);
|
||||
assert_eq!(
|
||||
interpreter.generation_state.memory.get(MemoryAddress::new(
|
||||
0,
|
||||
GlobalMetadata,
|
||||
AccessedAddressesLen as usize
|
||||
)),
|
||||
U256::from(n + 1)
|
||||
);
|
||||
assert_eq!(
|
||||
interpreter
|
||||
.generation_state
|
||||
.memory
|
||||
.get(MemoryAddress::new(0, AccessedAddresses, n)),
|
||||
U256::from(addr_not_in_list.0.as_slice())
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_accessed_storage_keys() -> Result<()> {
|
||||
let insert_accessed_storage_keys = KERNEL.global_labels["insert_accessed_storage_keys"];
|
||||
|
||||
let retaddr = 0xdeadbeefu32.into();
|
||||
let mut rng = thread_rng();
|
||||
let n = rng.gen_range(1..10);
|
||||
let storage_keys = (0..n)
|
||||
.map(|_| (rng.gen::<Address>(), U256(rng.gen())))
|
||||
.collect::<HashSet<_>>()
|
||||
.into_iter()
|
||||
.collect::<Vec<(Address, U256)>>();
|
||||
let storage_key_in_list = storage_keys[rng.gen_range(0..n)];
|
||||
let storage_key_not_in_list = (rng.gen::<Address>(), U256(rng.gen()));
|
||||
assert!(
|
||||
!storage_keys.contains(&storage_key_not_in_list),
|
||||
"Cosmic luck or bad RNG?"
|
||||
);
|
||||
|
||||
// Test for storage key already in list.
|
||||
let initial_stack = vec![
|
||||
retaddr,
|
||||
storage_key_in_list.1,
|
||||
U256::from(storage_key_in_list.0 .0.as_slice()),
|
||||
];
|
||||
let mut interpreter = Interpreter::new_with_kernel(insert_accessed_storage_keys, initial_stack);
|
||||
for i in 0..n {
|
||||
let addr = U256::from(storage_keys[i].0 .0.as_slice());
|
||||
interpreter
|
||||
.generation_state
|
||||
.memory
|
||||
.set(MemoryAddress::new(0, AccessedStorageKeys, 2 * i), addr);
|
||||
interpreter.generation_state.memory.set(
|
||||
MemoryAddress::new(0, AccessedStorageKeys, 2 * i + 1),
|
||||
storage_keys[i].1,
|
||||
);
|
||||
}
|
||||
interpreter.generation_state.memory.set(
|
||||
MemoryAddress::new(0, GlobalMetadata, AccessedStorageKeysLen as usize),
|
||||
U256::from(2 * n),
|
||||
);
|
||||
interpreter.run()?;
|
||||
assert_eq!(interpreter.stack(), &[U256::zero()]);
|
||||
assert_eq!(
|
||||
interpreter.generation_state.memory.get(MemoryAddress::new(
|
||||
0,
|
||||
GlobalMetadata,
|
||||
AccessedStorageKeysLen as usize
|
||||
)),
|
||||
U256::from(2 * n)
|
||||
);
|
||||
|
||||
// Test for storage key not in list.
|
||||
let initial_stack = vec![
|
||||
retaddr,
|
||||
storage_key_not_in_list.1,
|
||||
U256::from(storage_key_not_in_list.0 .0.as_slice()),
|
||||
];
|
||||
let mut interpreter = Interpreter::new_with_kernel(insert_accessed_storage_keys, initial_stack);
|
||||
for i in 0..n {
|
||||
let addr = U256::from(storage_keys[i].0 .0.as_slice());
|
||||
interpreter
|
||||
.generation_state
|
||||
.memory
|
||||
.set(MemoryAddress::new(0, AccessedStorageKeys, 2 * i), addr);
|
||||
interpreter.generation_state.memory.set(
|
||||
MemoryAddress::new(0, AccessedStorageKeys, 2 * i + 1),
|
||||
storage_keys[i].1,
|
||||
);
|
||||
}
|
||||
interpreter.generation_state.memory.set(
|
||||
MemoryAddress::new(0, GlobalMetadata, AccessedStorageKeysLen as usize),
|
||||
U256::from(2 * n),
|
||||
);
|
||||
interpreter.run()?;
|
||||
assert_eq!(interpreter.stack(), &[U256::one()]);
|
||||
assert_eq!(
|
||||
interpreter.generation_state.memory.get(MemoryAddress::new(
|
||||
0,
|
||||
GlobalMetadata,
|
||||
AccessedStorageKeysLen as usize
|
||||
)),
|
||||
U256::from(2 * (n + 1))
|
||||
);
|
||||
assert_eq!(
|
||||
interpreter
|
||||
.generation_state
|
||||
.memory
|
||||
.get(MemoryAddress::new(0, AccessedStorageKeys, 2 * n,)),
|
||||
U256::from(storage_key_not_in_list.0 .0.as_slice())
|
||||
);
|
||||
assert_eq!(
|
||||
interpreter.generation_state.memory.get(MemoryAddress::new(
|
||||
0,
|
||||
AccessedStorageKeys,
|
||||
2 * n + 1,
|
||||
)),
|
||||
storage_key_not_in_list.1
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
mod access_lists;
|
||||
mod create_addresses;
|
||||
mod intrinsic_gas;
|
||||
mod jumpdest_analysis;
|
||||
|
||||
@ -44,10 +44,14 @@ pub enum Segment {
|
||||
BnWnafB = 20,
|
||||
BnTableQ = 21,
|
||||
BnPairing = 22,
|
||||
/// List of addresses that have been accessed in the current transaction.
|
||||
AccessedAddresses = 23,
|
||||
/// List of storage keys that have been accessed in the current transaction.
|
||||
AccessedStorageKeys = 24,
|
||||
}
|
||||
|
||||
impl Segment {
|
||||
pub(crate) const COUNT: usize = 23;
|
||||
pub(crate) const COUNT: usize = 25;
|
||||
|
||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||
[
|
||||
@ -74,6 +78,8 @@ impl Segment {
|
||||
Self::BnWnafB,
|
||||
Self::BnTableQ,
|
||||
Self::BnPairing,
|
||||
Self::AccessedAddresses,
|
||||
Self::AccessedStorageKeys,
|
||||
]
|
||||
}
|
||||
|
||||
@ -103,6 +109,8 @@ impl Segment {
|
||||
Segment::BnWnafB => "SEGMENT_KERNEL_BN_WNAF_B",
|
||||
Segment::BnTableQ => "SEGMENT_KERNEL_BN_TABLE_Q",
|
||||
Segment::BnPairing => "SEGMENT_KERNEL_BN_PAIRING",
|
||||
Segment::AccessedAddresses => "SEGMENT_ACCESSED_ADDRESSES",
|
||||
Segment::AccessedStorageKeys => "SEGMENT_ACCESSED_STORAGE_KEYS",
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,6 +140,8 @@ impl Segment {
|
||||
Segment::BnWnafB => 8,
|
||||
Segment::BnTableQ => 256,
|
||||
Segment::BnPairing => 256,
|
||||
Segment::AccessedAddresses => 256,
|
||||
Segment::AccessedStorageKeys => 256,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user