mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 14:53:08 +00:00
Selfdestruct gas and set (#947)
* Add new segment and global metadata * Insert into self-destruct set * Implement sys_selfdestruct * PR feedback * Fix stack underflow * Forgot that NOT 1 ≠ 0. Added %not_bit macro for that.
This commit is contained in:
parent
786a71d678
commit
2ca00a9ad4
@ -37,6 +37,7 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
include_str!("asm/core/transfer.asm"),
|
||||
include_str!("asm/core/util.asm"),
|
||||
include_str!("asm/core/access_lists.asm"),
|
||||
include_str!("asm/core/selfdestruct_set.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"),
|
||||
|
||||
43
evm/src/cpu/kernel/asm/core/selfdestruct_set.asm
Normal file
43
evm/src/cpu/kernel/asm/core/selfdestruct_set.asm
Normal file
@ -0,0 +1,43 @@
|
||||
/// Self-destruct set.
|
||||
/// Essentially the same code as in `access_lists.asm`, with the exception that the insert function doesn't return anything.
|
||||
/// TODO: Would it make sense to merge this with `access_lists.asm`?
|
||||
/// TODO: Look into using a more efficient data structure.
|
||||
|
||||
%macro insert_selfdestruct_set
|
||||
%stack (addr) -> (addr, %%after)
|
||||
%jump(insert_selfdestruct_set)
|
||||
%%after:
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
/// Inserts the address into the self-destruct set if it is not already present.
|
||||
global insert_selfdestruct_set:
|
||||
// stack: addr, retdest
|
||||
%mload_global_metadata(@GLOBAL_METADATA_SELFDESTRUCT_SET_LEN)
|
||||
// stack: len, addr, retdest
|
||||
PUSH 0
|
||||
insert_selfdestruct_set_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_SELFDESTRUCT_SET)
|
||||
// stack: loaded_addr, i, len, addr, retdest
|
||||
DUP4
|
||||
// stack: addr, loaded_addr, i, len, addr, retdest
|
||||
EQ %jumpi(insert_address_found)
|
||||
// stack: i, len, addr, retdest
|
||||
%increment
|
||||
%jump(insert_selfdestruct_set_loop)
|
||||
|
||||
insert_address:
|
||||
%stack (i, len, addr, retdest) -> (i, addr, len, retdest)
|
||||
%mstore_kernel(@SEGMENT_SELFDESTRUCT_SET) // Store new address at the end of the array.
|
||||
// stack: len, retdest
|
||||
%increment
|
||||
%mstore_global_metadata(@GLOBAL_METADATA_SELFDESTRUCT_SET_LEN) // Store new length.
|
||||
JUMP
|
||||
|
||||
insert_address_found:
|
||||
// stack: i, len, addr, retdest
|
||||
%pop3
|
||||
JUMP
|
||||
@ -22,17 +22,60 @@ global sys_return:
|
||||
%jump(terminate_common)
|
||||
|
||||
global sys_selfdestruct:
|
||||
// stack: kexit_info, address
|
||||
// stack: kexit_info, recipient
|
||||
SWAP1 %u256_to_addr
|
||||
DUP1 %insert_accessed_addresses_no_return // TODO: Use return value in gas calculation.
|
||||
// stack: address, kexit_info
|
||||
POP // TODO: Transfer balance to address.
|
||||
%address DUP1 %balance
|
||||
|
||||
// Insert recipient into the accessed addresses list.
|
||||
// stack: balance, address, recipient, kexit_info
|
||||
DUP3 %insert_accessed_addresses
|
||||
|
||||
// Compute gas.
|
||||
// stack: cold_access, balance, address, recipient, kexit_info
|
||||
%mul_const(@GAS_COLDACCOUNTACCESS)
|
||||
DUP2
|
||||
// stack: balance, gas_coldaccess, balance, address, recipient, kexit_info
|
||||
ISZERO %not_bit
|
||||
// stack: balance!=0, gas_coldaccess, balance, address, recipient, kexit_info
|
||||
DUP5 %is_dead MUL %mul_const(@GAS_NEWACCOUNT)
|
||||
// stack: gas_newaccount, gas_coldaccess, balance, address, recipient, kexit_info
|
||||
ADD %add_const(@GAS_SELFDESTRUCT)
|
||||
%stack (gas, balance, address, recipient, kexit_info) -> (gas, kexit_info, balance, address, recipient)
|
||||
%charge_gas
|
||||
%stack (kexit_info, balance, address, recipient) -> (balance, address, recipient, kexit_info)
|
||||
|
||||
// Insert address into the selfdestruct set.
|
||||
// stack: balance, address, recipient, kexit_info
|
||||
DUP2 %insert_selfdestruct_set
|
||||
|
||||
// Set the balance of the address to 0.
|
||||
// stack: balance, address, recipient, kexit_info
|
||||
PUSH 0
|
||||
// stack: 0, balance, address, recipient, kexit_info
|
||||
DUP3 %mpt_read_state_trie
|
||||
// stack: account_ptr, 0, balance, address, recipient, kexit_info
|
||||
%add_const(1)
|
||||
// stack: balance_ptr, 0, balance, address, recipient, kexit_info
|
||||
%mstore_trie_data // TODO: This should be a copy-on-write operation.
|
||||
|
||||
// If the recipient is the same as the address, then we're done.
|
||||
// Otherwise, send the balance to the recipient.
|
||||
%stack (balance, address, recipient, kexit_info) -> (address, recipient, recipient, balance, kexit_info)
|
||||
EQ %jumpi(sys_selfdestruct_same_addr)
|
||||
// stack: recipient, balance, kexit_info
|
||||
%add_eth
|
||||
|
||||
// stack: kexit_info
|
||||
// TODO: Add address to the access list.
|
||||
%charge_gas_const(@GAS_SELFDESTRUCT)
|
||||
%leftover_gas
|
||||
// stack: leftover_gas
|
||||
// TODO: Destroy account.
|
||||
PUSH 1 // success
|
||||
%jump(terminate_common)
|
||||
|
||||
sys_selfdestruct_same_addr:
|
||||
// stack: recipient, balance, kexit_info
|
||||
%pop2
|
||||
%leftover_gas
|
||||
// stack: leftover_gas
|
||||
PUSH 1 // success
|
||||
%jump(terminate_common)
|
||||
|
||||
|
||||
@ -81,9 +81,10 @@ global add_eth:
|
||||
// stack: retdest
|
||||
JUMP
|
||||
global add_eth_new_account:
|
||||
// TODO: Skip creation if amount == 0?
|
||||
// stack: null_account_ptr, addr, amount, retdest
|
||||
POP
|
||||
// stack: addr, amount, retdest
|
||||
DUP2 ISZERO %jumpi(add_eth_new_account_zero)
|
||||
%get_trie_data_size // pointer to new account we're about to create
|
||||
// stack: new_account_ptr, addr, amount, retdest
|
||||
SWAP2
|
||||
@ -98,6 +99,10 @@ global add_eth_new_account:
|
||||
// stack: key, new_account_ptr, retdest
|
||||
%jump(mpt_insert_state_trie)
|
||||
|
||||
add_eth_new_account_zero:
|
||||
// stack: addr, amount, retdest
|
||||
%pop2 JUMP
|
||||
|
||||
// Convenience macro to call add_eth and return where we left off.
|
||||
%macro add_eth
|
||||
%stack (addr, amount) -> (addr, amount, %%after)
|
||||
|
||||
@ -30,3 +30,43 @@
|
||||
// If there is no "to" field, then this is a contract creation.
|
||||
// stack: to == 0
|
||||
%endmacro
|
||||
|
||||
// Returns 1 if the account is non-existent, 0 otherwise.
|
||||
%macro is_non_existent
|
||||
// stack: addr
|
||||
%mpt_read_state_trie
|
||||
ISZERO
|
||||
%endmacro
|
||||
|
||||
// Returns 1 if the account is empty, 0 otherwise.
|
||||
%macro is_empty
|
||||
// stack: addr
|
||||
%mpt_read_state_trie
|
||||
// stack: account_ptr
|
||||
DUP1 ISZERO %jumpi(%%false)
|
||||
// stack: account_ptr
|
||||
DUP1 %mload_trie_data
|
||||
// stack: nonce, account_ptr
|
||||
ISZERO %not_bit %jumpi(%%false)
|
||||
%increment DUP1 %mload_trie_data
|
||||
// stack: balance, balance_ptr
|
||||
ISZERO %not_bit %jumpi(%%false)
|
||||
%add_const(2) %mload_trie_data
|
||||
// stack: code_hash
|
||||
PUSH @EMPTY_STRING_HASH
|
||||
EQ
|
||||
%jump(%%after)
|
||||
%%false:
|
||||
// stack: account_ptr
|
||||
POP
|
||||
PUSH 0
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
// Returns 1 if the account is dead (i.e., empty or non-existent), 0 otherwise.
|
||||
%macro is_dead
|
||||
// stack: addr
|
||||
DUP1 %is_non_existent
|
||||
SWAP1 %is_empty
|
||||
ADD // OR
|
||||
%endmacro
|
||||
@ -345,3 +345,11 @@
|
||||
// stack: x
|
||||
%mod_const(0x10000000000000000000000000000000000000000) // 2^160
|
||||
%endmacro
|
||||
|
||||
%macro not_bit
|
||||
// stack: b
|
||||
PUSH 1
|
||||
// stack: 1, b
|
||||
SUB
|
||||
// stack: 1 - b
|
||||
%endmacro
|
||||
|
||||
@ -49,10 +49,12 @@ pub(crate) enum GlobalMetadata {
|
||||
AccessedAddressesLen = 23,
|
||||
/// Length of the storage keys access list.
|
||||
AccessedStorageKeysLen = 24,
|
||||
/// Length of the self-destruct set.
|
||||
SelfDestructSetLen = 25,
|
||||
}
|
||||
|
||||
impl GlobalMetadata {
|
||||
pub(crate) const COUNT: usize = 24;
|
||||
pub(crate) const COUNT: usize = 25;
|
||||
|
||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||
[
|
||||
@ -80,6 +82,7 @@ impl GlobalMetadata {
|
||||
Self::RefundCounter,
|
||||
Self::AccessedAddressesLen,
|
||||
Self::AccessedStorageKeysLen,
|
||||
Self::SelfDestructSetLen,
|
||||
]
|
||||
}
|
||||
|
||||
@ -110,6 +113,7 @@ impl GlobalMetadata {
|
||||
Self::RefundCounter => "GLOBAL_METADATA_REFUND_COUNTER",
|
||||
Self::AccessedAddressesLen => "GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN",
|
||||
Self::AccessedStorageKeysLen => "GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN",
|
||||
Self::SelfDestructSetLen => "GLOBAL_METADATA_SELFDESTRUCT_SET_LEN",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,10 +48,12 @@ pub enum Segment {
|
||||
AccessedAddresses = 23,
|
||||
/// List of storage keys that have been accessed in the current transaction.
|
||||
AccessedStorageKeys = 24,
|
||||
/// List of addresses that have called SELFDESTRUCT in the current transaction.
|
||||
SelfDestructSet = 25,
|
||||
}
|
||||
|
||||
impl Segment {
|
||||
pub(crate) const COUNT: usize = 25;
|
||||
pub(crate) const COUNT: usize = 26;
|
||||
|
||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||
[
|
||||
@ -80,6 +82,7 @@ impl Segment {
|
||||
Self::BnPairing,
|
||||
Self::AccessedAddresses,
|
||||
Self::AccessedStorageKeys,
|
||||
Self::SelfDestructSet,
|
||||
]
|
||||
}
|
||||
|
||||
@ -111,6 +114,7 @@ impl Segment {
|
||||
Segment::BnPairing => "SEGMENT_KERNEL_BN_PAIRING",
|
||||
Segment::AccessedAddresses => "SEGMENT_ACCESSED_ADDRESSES",
|
||||
Segment::AccessedStorageKeys => "SEGMENT_ACCESSED_STORAGE_KEYS",
|
||||
Segment::SelfDestructSet => "SEGMENT_SELFDESTRUCT_SET",
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,6 +146,7 @@ impl Segment {
|
||||
Segment::BnPairing => 256,
|
||||
Segment::AccessedAddresses => 256,
|
||||
Segment::AccessedStorageKeys => 256,
|
||||
Segment::SelfDestructSet => 256,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user