This commit is contained in:
Dmitry Vagner 2023-03-24 11:32:01 -07:00
commit c3a5fd8631
17 changed files with 439 additions and 10 deletions

View File

@ -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"),

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -345,3 +345,8 @@
%endrep
// stack: a || b || c || d
%endmacro
%macro u256_to_addr
// stack: x
%mod_const(0x10000000000000000000000000000000000000000) // 2^160
%endmacro

View File

@ -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",
}
}
}

View File

@ -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),
];

View File

@ -59,6 +59,7 @@ pub fn run_interpreter(
)
}
#[derive(Clone)]
pub struct InterpreterMemoryInitialization {
pub label: String,
pub stack: Vec<U256>,

View 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(())
}

View File

@ -1,3 +1,4 @@
mod access_lists;
mod create_addresses;
mod intrinsic_gas;
mod jumpdest_analysis;

View File

@ -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,
}
}
}