mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 00:03:10 +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/transfer.asm"),
|
||||||
include_str!("asm/core/util.asm"),
|
include_str!("asm/core/util.asm"),
|
||||||
include_str!("asm/core/access_lists.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/bls381/util.asm"),
|
||||||
include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"),
|
include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"),
|
||||||
include_str!("asm/curve/bn254/curve_arithmetic/curve_add.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)
|
%jump(terminate_common)
|
||||||
|
|
||||||
global sys_selfdestruct:
|
global sys_selfdestruct:
|
||||||
// stack: kexit_info, address
|
// stack: kexit_info, recipient
|
||||||
SWAP1 %u256_to_addr
|
SWAP1 %u256_to_addr
|
||||||
DUP1 %insert_accessed_addresses_no_return // TODO: Use return value in gas calculation.
|
%address DUP1 %balance
|
||||||
// stack: address, kexit_info
|
|
||||||
POP // TODO: Transfer balance to address.
|
// 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
|
// stack: kexit_info
|
||||||
// TODO: Add address to the access list.
|
|
||||||
%charge_gas_const(@GAS_SELFDESTRUCT)
|
|
||||||
%leftover_gas
|
%leftover_gas
|
||||||
// stack: 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
|
PUSH 1 // success
|
||||||
%jump(terminate_common)
|
%jump(terminate_common)
|
||||||
|
|
||||||
|
|||||||
@ -81,9 +81,10 @@ global add_eth:
|
|||||||
// stack: retdest
|
// stack: retdest
|
||||||
JUMP
|
JUMP
|
||||||
global add_eth_new_account:
|
global add_eth_new_account:
|
||||||
// TODO: Skip creation if amount == 0?
|
|
||||||
// stack: null_account_ptr, addr, amount, retdest
|
// stack: null_account_ptr, addr, amount, retdest
|
||||||
POP
|
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
|
%get_trie_data_size // pointer to new account we're about to create
|
||||||
// stack: new_account_ptr, addr, amount, retdest
|
// stack: new_account_ptr, addr, amount, retdest
|
||||||
SWAP2
|
SWAP2
|
||||||
@ -98,6 +99,10 @@ global add_eth_new_account:
|
|||||||
// stack: key, new_account_ptr, retdest
|
// stack: key, new_account_ptr, retdest
|
||||||
%jump(mpt_insert_state_trie)
|
%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.
|
// Convenience macro to call add_eth and return where we left off.
|
||||||
%macro add_eth
|
%macro add_eth
|
||||||
%stack (addr, amount) -> (addr, amount, %%after)
|
%stack (addr, amount) -> (addr, amount, %%after)
|
||||||
|
|||||||
@ -30,3 +30,43 @@
|
|||||||
// If there is no "to" field, then this is a contract creation.
|
// If there is no "to" field, then this is a contract creation.
|
||||||
// stack: to == 0
|
// stack: to == 0
|
||||||
%endmacro
|
%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
|
// stack: x
|
||||||
%mod_const(0x10000000000000000000000000000000000000000) // 2^160
|
%mod_const(0x10000000000000000000000000000000000000000) // 2^160
|
||||||
%endmacro
|
%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,
|
AccessedAddressesLen = 23,
|
||||||
/// Length of the storage keys access list.
|
/// Length of the storage keys access list.
|
||||||
AccessedStorageKeysLen = 24,
|
AccessedStorageKeysLen = 24,
|
||||||
|
/// Length of the self-destruct set.
|
||||||
|
SelfDestructSetLen = 25,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalMetadata {
|
impl GlobalMetadata {
|
||||||
pub(crate) const COUNT: usize = 24;
|
pub(crate) const COUNT: usize = 25;
|
||||||
|
|
||||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||||
[
|
[
|
||||||
@ -80,6 +82,7 @@ impl GlobalMetadata {
|
|||||||
Self::RefundCounter,
|
Self::RefundCounter,
|
||||||
Self::AccessedAddressesLen,
|
Self::AccessedAddressesLen,
|
||||||
Self::AccessedStorageKeysLen,
|
Self::AccessedStorageKeysLen,
|
||||||
|
Self::SelfDestructSetLen,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +113,7 @@ impl GlobalMetadata {
|
|||||||
Self::RefundCounter => "GLOBAL_METADATA_REFUND_COUNTER",
|
Self::RefundCounter => "GLOBAL_METADATA_REFUND_COUNTER",
|
||||||
Self::AccessedAddressesLen => "GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN",
|
Self::AccessedAddressesLen => "GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN",
|
||||||
Self::AccessedStorageKeysLen => "GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_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,
|
AccessedAddresses = 23,
|
||||||
/// List of storage keys that have been accessed in the current transaction.
|
/// List of storage keys that have been accessed in the current transaction.
|
||||||
AccessedStorageKeys = 24,
|
AccessedStorageKeys = 24,
|
||||||
|
/// List of addresses that have called SELFDESTRUCT in the current transaction.
|
||||||
|
SelfDestructSet = 25,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Segment {
|
impl Segment {
|
||||||
pub(crate) const COUNT: usize = 25;
|
pub(crate) const COUNT: usize = 26;
|
||||||
|
|
||||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||||
[
|
[
|
||||||
@ -80,6 +82,7 @@ impl Segment {
|
|||||||
Self::BnPairing,
|
Self::BnPairing,
|
||||||
Self::AccessedAddresses,
|
Self::AccessedAddresses,
|
||||||
Self::AccessedStorageKeys,
|
Self::AccessedStorageKeys,
|
||||||
|
Self::SelfDestructSet,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +114,7 @@ impl Segment {
|
|||||||
Segment::BnPairing => "SEGMENT_KERNEL_BN_PAIRING",
|
Segment::BnPairing => "SEGMENT_KERNEL_BN_PAIRING",
|
||||||
Segment::AccessedAddresses => "SEGMENT_ACCESSED_ADDRESSES",
|
Segment::AccessedAddresses => "SEGMENT_ACCESSED_ADDRESSES",
|
||||||
Segment::AccessedStorageKeys => "SEGMENT_ACCESSED_STORAGE_KEYS",
|
Segment::AccessedStorageKeys => "SEGMENT_ACCESSED_STORAGE_KEYS",
|
||||||
|
Segment::SelfDestructSet => "SEGMENT_SELFDESTRUCT_SET",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +146,7 @@ impl Segment {
|
|||||||
Segment::BnPairing => 256,
|
Segment::BnPairing => 256,
|
||||||
Segment::AccessedAddresses => 256,
|
Segment::AccessedAddresses => 256,
|
||||||
Segment::AccessedStorageKeys => 256,
|
Segment::AccessedStorageKeys => 256,
|
||||||
|
Segment::SelfDestructSet => 256,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user