mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-10 17:53:06 +00:00
Misc EVM fixes
This commit is contained in:
parent
57ea64e303
commit
c558eedd65
@ -93,6 +93,7 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
include_str!("asm/rlp/num_bytes.asm"),
|
||||
include_str!("asm/rlp/read_to_memory.asm"),
|
||||
include_str!("asm/shift.asm"),
|
||||
include_str!("asm/transactions/common_decoding.asm"),
|
||||
include_str!("asm/transactions/router.asm"),
|
||||
include_str!("asm/transactions/type_0.asm"),
|
||||
include_str!("asm/transactions/type_1.asm"),
|
||||
|
||||
@ -36,20 +36,43 @@ global extcodehash:
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
global sys_extcodesize:
|
||||
// stack: kexit_info, address
|
||||
SWAP1
|
||||
// stack: address, kexit_info
|
||||
%extcodesize
|
||||
// stack: code_size, kexit_info
|
||||
SWAP1
|
||||
EXIT_KERNEL
|
||||
|
||||
global extcodesize:
|
||||
// stack: address, retdest
|
||||
%extcodesize
|
||||
// stack: extcodesize(address), retdest
|
||||
SWAP1 JUMP
|
||||
|
||||
|
||||
%macro codecopy
|
||||
// stack: dest_offset, offset, size, retdest
|
||||
// stack: dest_offset, offset, size
|
||||
%address
|
||||
// stack: address, dest_offset, offset, size, retdest
|
||||
%jump(extcodecopy)
|
||||
%extcodecopy
|
||||
%endmacro
|
||||
|
||||
%macro extcodecopy
|
||||
// stack: address, dest_offset, offset, size
|
||||
%stack (dest_offset, offset, size) -> (dest_offset, offset, size, %%after)
|
||||
%jump(extcodecopy)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
// Pre stack: kexit_info, address, dest_offset, offset, size
|
||||
// Post stack: (empty)
|
||||
global sys_extcodecopy:
|
||||
%stack (kexit_info, address, dest_offset, offset, size)
|
||||
-> (address, dest_offset, offset, size, kexit_info)
|
||||
%extcodecopy
|
||||
// stack: kexit_info
|
||||
EXIT_KERNEL
|
||||
|
||||
// Pre stack: address, dest_offset, offset, size, retdest
|
||||
// Post stack: (empty)
|
||||
global extcodecopy:
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
// Handlers for call-like operations, namely CALL, CALLCODE, STATICCALL and DELEGATECALL.
|
||||
|
||||
// TODO: Take kexit_info
|
||||
|
||||
// Creates a new sub context and executes the code of the given account.
|
||||
global call:
|
||||
// stack: gas, address, value, args_offset, args_size, ret_offset, ret_size, retdest
|
||||
// stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
%address
|
||||
%stack (self, gas, address, value)
|
||||
// These are (static, should_transfer_value, value, sender, address, code_addr, gas)
|
||||
|
||||
@ -29,6 +29,7 @@ global validate:
|
||||
// TODO: Assert nonce is correct.
|
||||
// TODO: Assert sender has no code.
|
||||
// TODO: Assert sender balance >= gas_limit * gas_price + value.
|
||||
// TODO: Assert chain ID matches block metadata?
|
||||
// stack: retdest
|
||||
|
||||
global buy_gas:
|
||||
@ -109,7 +110,7 @@ global process_message_txn_insufficient_balance:
|
||||
PANIC // TODO
|
||||
|
||||
global process_message_txn_return:
|
||||
// TODO: Return leftover gas?
|
||||
// TODO: Since there was no code to execute, do we still return leftover gas?
|
||||
JUMP
|
||||
|
||||
global process_message_txn_code_loaded:
|
||||
@ -159,9 +160,15 @@ global process_message_txn_code_loaded:
|
||||
MSTORE_GENERAL
|
||||
// stack: new_ctx, retdest
|
||||
|
||||
// TODO: Populate CALLDATA
|
||||
// Set the new context's gas limit.
|
||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
PUSH @CTX_METADATA_GAS_LIMIT
|
||||
PUSH @SEGMENT_CONTEXT_METADATA
|
||||
DUP4 // new_ctx
|
||||
MSTORE_GENERAL
|
||||
// stack: new_ctx, retdest
|
||||
|
||||
// TODO: Save parent gas and set child gas
|
||||
// TODO: Copy TXN_DATA to CALLDATA
|
||||
|
||||
// Now, switch to the new context and go to usermode with PC=0.
|
||||
SET_CONTEXT
|
||||
@ -171,6 +178,5 @@ global process_message_txn_code_loaded:
|
||||
|
||||
global process_message_txn_after_call:
|
||||
// stack: success, retdest
|
||||
// TODO: Return leftover gas? Or handled by termination instructions?
|
||||
POP // Pop success for now. Will go into the receipt when we support that.
|
||||
JUMP
|
||||
|
||||
@ -34,11 +34,11 @@ global sys_codesize:
|
||||
global sys_codecopy:
|
||||
PANIC
|
||||
global sys_gasprice:
|
||||
PANIC
|
||||
global sys_extcodesize:
|
||||
PANIC
|
||||
global sys_extcodecopy:
|
||||
PANIC
|
||||
// stack: kexit_info
|
||||
%mload_txn_field(@TXN_FIELD_COMPUTED_FEE_PER_GAS)
|
||||
// stack: gas_price, kexit_info
|
||||
SWAP1
|
||||
EXIT_KERNEL
|
||||
global sys_returndatasize:
|
||||
PANIC
|
||||
global sys_returndatacopy:
|
||||
@ -54,17 +54,28 @@ global sys_timestamp:
|
||||
global sys_number:
|
||||
PANIC
|
||||
global sys_prevrandao:
|
||||
// TODO: What semantics will this have for Edge?
|
||||
PANIC
|
||||
global sys_gaslimit:
|
||||
// TODO: Return the block's gas limit.
|
||||
PANIC
|
||||
global sys_chainid:
|
||||
PANIC
|
||||
// TODO: Return the block's chain ID instead of the txn's, even though they should match.
|
||||
// stack: kexit_info
|
||||
%mload_txn_field(@TXN_FIELD_CHAIN_ID)
|
||||
// stack: chain_id, kexit_info
|
||||
SWAP1
|
||||
EXIT_KERNEL
|
||||
global sys_selfbalance:
|
||||
PANIC
|
||||
global sys_basefee:
|
||||
PANIC
|
||||
global sys_msize:
|
||||
PANIC
|
||||
// stack: kexit_info
|
||||
%mload_context_metadata(@CTX_METADATA_MSIZE)
|
||||
// stack: msize, kexit_info
|
||||
SWAP1
|
||||
EXIT_KERNEL
|
||||
global sys_gas:
|
||||
PANIC
|
||||
global sys_log0:
|
||||
|
||||
@ -2,28 +2,36 @@
|
||||
// RETURN, SELFDESTRUCT, REVERT, and exceptions such as stack underflow.
|
||||
|
||||
global sys_stop:
|
||||
// stack: kexit_info
|
||||
%refund_leftover_gas
|
||||
// stack: (empty)
|
||||
// TODO: Set parent context's CTX_METADATA_RETURNDATA_SIZE to 0.
|
||||
// TODO: Refund unused gas to parent.
|
||||
PUSH 1 // success
|
||||
%jump(terminate_common)
|
||||
|
||||
global sys_return:
|
||||
// stack: kexit_info
|
||||
%refund_leftover_gas
|
||||
// stack: (empty)
|
||||
// TODO: Set parent context's CTX_METADATA_RETURNDATA_SIZE.
|
||||
// TODO: Copy returned memory to parent context's RETURNDATA (but not if we're returning from a constructor?)
|
||||
// TODO: Copy returned memory to parent context's memory (as specified in their call instruction)
|
||||
// TODO: Refund unused gas to parent.
|
||||
PUSH 1 // success
|
||||
%jump(terminate_common)
|
||||
|
||||
global sys_selfdestruct:
|
||||
// stack: kexit_info
|
||||
%consume_gas_const(@GAS_SELFDESTRUCT)
|
||||
%refund_leftover_gas
|
||||
// stack: (empty)
|
||||
// TODO: Destroy account.
|
||||
// TODO: Refund unused gas to parent.
|
||||
PUSH 1 // success
|
||||
%jump(terminate_common)
|
||||
|
||||
global sys_revert:
|
||||
// TODO: Refund unused gas to parent.
|
||||
// stack: kexit_info
|
||||
%refund_leftover_gas
|
||||
// stack: (empty)
|
||||
// TODO: Revert state changes.
|
||||
PUSH 0 // success
|
||||
%jump(terminate_common)
|
||||
@ -68,3 +76,14 @@ terminate_common:
|
||||
|
||||
// stack: parent_pc, success
|
||||
JUMP
|
||||
|
||||
%macro refund_leftover_gas
|
||||
// stack: kexit_info
|
||||
%shr_const(192)
|
||||
// stack: gas_used
|
||||
%mload_context_metadata(@CTX_METADATA_GAS_LIMIT)
|
||||
SUB
|
||||
// stack: leftover_gas
|
||||
POP // TODO: Refund to caller.
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
@ -4,6 +4,12 @@
|
||||
// Post stack: (empty)
|
||||
|
||||
global sys_sstore:
|
||||
// TODO: Assuming a cold zero -> nonzero write for now.
|
||||
PUSH @GAS_COLDSLOAD
|
||||
PUSH @GAS_SSET
|
||||
ADD
|
||||
%charge_gas
|
||||
|
||||
%stack (kexit_info, slot, value) -> (slot, value, kexit_info)
|
||||
// TODO: If value = 0, delete the key instead of inserting 0.
|
||||
// stack: slot, value, kexit_info
|
||||
|
||||
139
evm/src/cpu/kernel/asm/transactions/common_decoding.asm
Normal file
139
evm/src/cpu/kernel/asm/transactions/common_decoding.asm
Normal file
@ -0,0 +1,139 @@
|
||||
// Store chain ID = 1. Used for non-legacy txns which always have a chain ID.
|
||||
%macro store_chain_id_present_true
|
||||
PUSH 1
|
||||
%mstore_txn_field(@TXN_FIELD_CHAIN_ID_PRESENT)
|
||||
%endmacro
|
||||
|
||||
// Decode the chain ID and store it.
|
||||
%macro decode_and_store_chain_id
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, chain_id) -> (chain_id, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_CHAIN_ID)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
// Decode the nonce and store it.
|
||||
%macro decode_and_store_nonce
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, nonce) -> (nonce, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_NONCE)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
// Decode the gas price and, since this is for legacy txns, store it as both
|
||||
// TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS and TXN_FIELD_MAX_FEE_PER_GAS.
|
||||
%macro decode_and_store_gas_price_legacy
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, gas_price) -> (gas_price, gas_price, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS)
|
||||
%mstore_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
// Decode the max priority fee and store it.
|
||||
%macro decode_and_store_max_priority_fee
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, gas_price) -> (gas_price, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
// Decode the max fee and store it.
|
||||
%macro decode_and_store_max_fee
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, gas_price) -> (gas_price, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
// Decode the gas limit and store it.
|
||||
%macro decode_and_store_gas_limit
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, gas_limit) -> (gas_limit, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
// Decode the "to" field and store it.
|
||||
%macro decode_and_store_to
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, to) -> (to, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_TO)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
// Decode the "value" field and store it.
|
||||
%macro decode_and_store_value
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, value) -> (value, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_VALUE)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
// Decode the calldata field, store its length in @TXN_FIELD_DATA_LEN, and copy it to @SEGMENT_TXN_DATA.
|
||||
%macro decode_and_store_data
|
||||
// stack: pos
|
||||
// Decode the data length, store it, and compute new_pos after any data.
|
||||
%decode_rlp_string_len
|
||||
%stack (pos, data_len) -> (data_len, pos, data_len, pos, data_len)
|
||||
%mstore_txn_field(@TXN_FIELD_DATA_LEN)
|
||||
// stack: pos, data_len, pos, data_len
|
||||
ADD
|
||||
// stack: new_pos, old_pos, data_len
|
||||
|
||||
// Memcpy the txn data from @SEGMENT_RLP_RAW to @SEGMENT_TXN_DATA.
|
||||
%stack (new_pos, old_pos, data_len) -> (old_pos, data_len, %%after, new_pos)
|
||||
PUSH @SEGMENT_RLP_RAW
|
||||
GET_CONTEXT
|
||||
PUSH 0
|
||||
PUSH @SEGMENT_TXN_DATA
|
||||
GET_CONTEXT
|
||||
// stack: DST, SRC, data_len, %%after, new_pos
|
||||
%jump(memcpy)
|
||||
|
||||
%%after:
|
||||
// stack: new_pos
|
||||
%endmacro
|
||||
|
||||
%macro decode_and_store_access_list
|
||||
// stack: pos
|
||||
%decode_rlp_list_len
|
||||
%stack (pos, len) -> (len, pos)
|
||||
%jumpi(todo_access_lists_not_supported_yet)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
%macro decode_and_store_y_parity
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, y_parity) -> (y_parity, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_Y_PARITY)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
%macro decode_and_store_r
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, r) -> (r, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_R)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
%macro decode_and_store_s
|
||||
// stack: pos
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, s) -> (s, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_S)
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
global todo_access_lists_not_supported_yet:
|
||||
PANIC
|
||||
@ -19,61 +19,16 @@ global process_type_0_txn:
|
||||
// We don't actually need the length.
|
||||
%stack (pos, len) -> (pos)
|
||||
|
||||
// Decode the nonce and store it.
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, nonce) -> (nonce, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_NONCE)
|
||||
|
||||
// Decode the gas price and store it.
|
||||
// For legacy transactions, we set both the
|
||||
// TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS and TXN_FIELD_MAX_FEE_PER_GAS
|
||||
// fields to gas_price.
|
||||
%decode_and_store_nonce
|
||||
%decode_and_store_gas_price_legacy
|
||||
%decode_and_store_gas_limit
|
||||
%decode_and_store_to
|
||||
%decode_and_store_value
|
||||
%decode_and_store_data
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, gas_price) -> (gas_price, gas_price, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS)
|
||||
%mstore_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
|
||||
|
||||
// Decode the gas limit and store it.
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, gas_limit) -> (gas_limit, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
|
||||
// Decode the "to" field and store it.
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, to) -> (to, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_TO)
|
||||
|
||||
// Decode the value field and store it.
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, value) -> (value, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_VALUE)
|
||||
|
||||
// Decode the data length, store it, and compute new_pos after any data.
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_string_len
|
||||
%stack (pos, data_len) -> (data_len, pos, data_len, pos, data_len)
|
||||
%mstore_txn_field(@TXN_FIELD_DATA_LEN)
|
||||
// stack: pos, data_len, pos, data_len, retdest
|
||||
ADD
|
||||
// stack: new_pos, pos, data_len, retdest
|
||||
|
||||
// Memcpy the txn data from @SEGMENT_RLP_RAW to @SEGMENT_TXN_DATA.
|
||||
PUSH parse_v
|
||||
%stack (parse_v, new_pos, old_pos, data_len) -> (old_pos, data_len, parse_v, new_pos)
|
||||
PUSH @SEGMENT_RLP_RAW
|
||||
GET_CONTEXT
|
||||
PUSH 0
|
||||
PUSH @SEGMENT_TXN_DATA
|
||||
GET_CONTEXT
|
||||
// stack: DST, SRC, data_len, parse_v, new_pos, retdest
|
||||
%jump(memcpy)
|
||||
|
||||
parse_v:
|
||||
// Parse the "v" field.
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_scalar
|
||||
// stack: pos, v, retdest
|
||||
@ -93,7 +48,7 @@ parse_v:
|
||||
%mstore_txn_field(@TXN_FIELD_Y_PARITY)
|
||||
|
||||
// stack: pos, retdest
|
||||
%jump(parse_r)
|
||||
%jump(decode_r_and_s)
|
||||
|
||||
process_v_new_style:
|
||||
// stack: v, pos, retdest
|
||||
@ -115,16 +70,12 @@ process_v_new_style:
|
||||
// stack: y_parity, pos, retdest
|
||||
%mstore_txn_field(@TXN_FIELD_Y_PARITY)
|
||||
|
||||
parse_r:
|
||||
decode_r_and_s:
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, r) -> (r, pos)
|
||||
%mstore_txn_field(@TXN_FIELD_R)
|
||||
|
||||
%decode_and_store_r
|
||||
%decode_and_store_s
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_scalar
|
||||
%stack (pos, s) -> (s)
|
||||
%mstore_txn_field(@TXN_FIELD_S)
|
||||
POP
|
||||
// stack: retdest
|
||||
|
||||
type_0_compute_signed_data:
|
||||
|
||||
@ -8,4 +8,29 @@
|
||||
|
||||
global process_type_1_txn:
|
||||
// stack: retdest
|
||||
PANIC // TODO: Unfinished
|
||||
PUSH 1 // initial pos, skipping over the 0x01 byte
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_list_len
|
||||
// We don't actually need the length.
|
||||
%stack (pos, len) -> (pos)
|
||||
|
||||
%store_chain_id_present_true
|
||||
%decode_and_store_chain_id
|
||||
%decode_and_store_nonce
|
||||
%decode_and_store_gas_price_legacy
|
||||
%decode_and_store_gas_limit
|
||||
%decode_and_store_to
|
||||
%decode_and_store_value
|
||||
%decode_and_store_data
|
||||
%decode_and_store_access_list
|
||||
%decode_and_store_y_parity
|
||||
%decode_and_store_r
|
||||
%decode_and_store_s
|
||||
|
||||
// stack: pos, retdest
|
||||
POP
|
||||
// stack: retdest
|
||||
|
||||
// TODO: Check signature.
|
||||
|
||||
%jump(process_normalized_txn)
|
||||
|
||||
@ -9,4 +9,31 @@
|
||||
|
||||
global process_type_2_txn:
|
||||
// stack: retdest
|
||||
PANIC // TODO: Unfinished
|
||||
PUSH 1 // initial pos, skipping over the 0x02 byte
|
||||
// stack: pos, retdest
|
||||
%decode_rlp_list_len
|
||||
// We don't actually need the length.
|
||||
%stack (pos, len) -> (pos)
|
||||
|
||||
// stack: pos, retdest
|
||||
%store_chain_id_present_true
|
||||
%decode_and_store_chain_id
|
||||
%decode_and_store_nonce
|
||||
%decode_and_store_max_priority_fee
|
||||
%decode_and_store_max_fee
|
||||
%decode_and_store_gas_limit
|
||||
%decode_and_store_to
|
||||
%decode_and_store_value
|
||||
%decode_and_store_data
|
||||
%decode_and_store_access_list
|
||||
%decode_and_store_y_parity
|
||||
%decode_and_store_r
|
||||
%decode_and_store_s
|
||||
|
||||
// stack: pos, retdest
|
||||
POP
|
||||
// stack: retdest
|
||||
|
||||
// TODO: Check signature.
|
||||
|
||||
%jump(process_normalized_txn)
|
||||
|
||||
@ -26,10 +26,12 @@ pub(crate) enum ContextMetadata {
|
||||
/// Size of the active main memory.
|
||||
MSize = 10,
|
||||
StackSize = 11,
|
||||
/// The gas limit for this call (not the entire transaction).
|
||||
GasLimit = 12,
|
||||
}
|
||||
|
||||
impl ContextMetadata {
|
||||
pub(crate) const COUNT: usize = 12;
|
||||
pub(crate) const COUNT: usize = 13;
|
||||
|
||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||
[
|
||||
@ -45,6 +47,7 @@ impl ContextMetadata {
|
||||
Self::StateTrieCheckpointPointer,
|
||||
Self::MSize,
|
||||
Self::StackSize,
|
||||
Self::GasLimit,
|
||||
]
|
||||
}
|
||||
|
||||
@ -63,6 +66,7 @@ impl ContextMetadata {
|
||||
ContextMetadata::StateTrieCheckpointPointer => "CTX_METADATA_STATE_TRIE_CHECKPOINT_PTR",
|
||||
ContextMetadata::MSize => "CTX_METADATA_MSIZE",
|
||||
ContextMetadata::StackSize => "CTX_METADATA_STACK_SIZE",
|
||||
ContextMetadata::GasLimit => "CTX_METADATA_GAS_LIMIT",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,12 +67,12 @@ pub(crate) fn generate_traces<F: RichField + Extendable<D>, const D: usize>(
|
||||
inputs: GenerationInputs,
|
||||
config: &StarkConfig,
|
||||
timing: &mut TimingTree,
|
||||
) -> ([Vec<PolynomialValues<F>>; NUM_TABLES], PublicValues) {
|
||||
) -> anyhow::Result<([Vec<PolynomialValues<F>>; NUM_TABLES], PublicValues)> {
|
||||
let mut state = GenerationState::<F>::new(inputs.clone(), &KERNEL.code);
|
||||
|
||||
generate_bootstrap_kernel::<F>(&mut state);
|
||||
|
||||
timed!(timing, "simulate CPU", simulate_cpu(&mut state));
|
||||
timed!(timing, "simulate CPU", simulate_cpu(&mut state)?);
|
||||
|
||||
log::info!(
|
||||
"Trace lengths (before padding): {:?}",
|
||||
@ -109,10 +109,12 @@ pub(crate) fn generate_traces<F: RichField + Extendable<D>, const D: usize>(
|
||||
"convert trace data to tables",
|
||||
state.traces.into_tables(all_stark, config, timing)
|
||||
);
|
||||
(tables, public_values)
|
||||
Ok((tables, public_values))
|
||||
}
|
||||
|
||||
fn simulate_cpu<F: RichField + Extendable<D>, const D: usize>(state: &mut GenerationState<F>) {
|
||||
fn simulate_cpu<F: RichField + Extendable<D>, const D: usize>(
|
||||
state: &mut GenerationState<F>,
|
||||
) -> anyhow::Result<()> {
|
||||
let halt_pc0 = KERNEL.global_labels["halt_pc0"];
|
||||
let halt_pc1 = KERNEL.global_labels["halt_pc1"];
|
||||
|
||||
@ -126,11 +128,13 @@ fn simulate_cpu<F: RichField + Extendable<D>, const D: usize>(state: &mut Genera
|
||||
}
|
||||
already_in_halt_loop |= in_halt_loop;
|
||||
|
||||
transition(state);
|
||||
transition(state)?;
|
||||
|
||||
if already_in_halt_loop && state.traces.clock().is_power_of_two() {
|
||||
log::info!("CPU trace padded to {} cycles", state.traces.clock());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -33,6 +33,15 @@ pub(crate) struct GenerationState<F: Field> {
|
||||
|
||||
impl<F: Field> GenerationState<F> {
|
||||
pub(crate) fn new(inputs: GenerationInputs, kernel_code: &[u8]) -> Self {
|
||||
log::debug!("Input signed_txns: {:?}", &inputs.signed_txns);
|
||||
log::debug!("Input state_trie: {:?}", &inputs.tries.state_trie);
|
||||
log::debug!(
|
||||
"Input transactions_trie: {:?}",
|
||||
&inputs.tries.transactions_trie
|
||||
);
|
||||
log::debug!("Input receipts_trie: {:?}", &inputs.tries.receipts_trie);
|
||||
log::debug!("Input storage_tries: {:?}", &inputs.tries.storage_tries);
|
||||
log::debug!("Input contract_code: {:?}", &inputs.contract_code);
|
||||
let mpt_prover_inputs = all_mpt_prover_inputs_reversed(&inputs.tries);
|
||||
let rlp_prover_inputs = all_rlp_prover_inputs_reversed(&inputs.signed_txns);
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ where
|
||||
let (traces, public_values) = timed!(
|
||||
timing,
|
||||
"generate all traces",
|
||||
generate_traces(all_stark, inputs, config, timing)
|
||||
generate_traces(all_stark, inputs, config, timing)?
|
||||
);
|
||||
prove_with_traces(all_stark, config, traces, public_values, timing)
|
||||
}
|
||||
|
||||
@ -7,4 +7,5 @@ pub enum ProgramError {
|
||||
InvalidJumpDestination,
|
||||
InvalidJumpiDestination,
|
||||
StackOverflow,
|
||||
KernelPanic,
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use anyhow::bail;
|
||||
use itertools::Itertools;
|
||||
use log::log_enabled;
|
||||
use plonky2::field::types::Field;
|
||||
@ -117,10 +118,13 @@ fn decode(registers: RegistersState, opcode: u8) -> Result<Operation, ProgramErr
|
||||
(0xa2, _) => Ok(Operation::Syscall(opcode)),
|
||||
(0xa3, _) => Ok(Operation::Syscall(opcode)),
|
||||
(0xa4, _) => Ok(Operation::Syscall(opcode)),
|
||||
(0xa5, _) => panic!(
|
||||
"Kernel panic at {}",
|
||||
KERNEL.offset_name(registers.program_counter)
|
||||
),
|
||||
(0xa5, _) => {
|
||||
log::warn!(
|
||||
"Kernel panic at {}",
|
||||
KERNEL.offset_name(registers.program_counter)
|
||||
);
|
||||
Err(ProgramError::KernelPanic)
|
||||
}
|
||||
(0xf0, _) => Ok(Operation::Syscall(opcode)),
|
||||
(0xf1, _) => Ok(Operation::Syscall(opcode)),
|
||||
(0xf2, _) => Ok(Operation::Syscall(opcode)),
|
||||
@ -288,11 +292,11 @@ fn log_kernel_instruction<F: Field>(state: &mut GenerationState<F>, op: Operatio
|
||||
assert!(pc < KERNEL.code.len(), "Kernel PC is out of range: {}", pc);
|
||||
}
|
||||
|
||||
fn handle_error<F: Field>(_state: &mut GenerationState<F>) {
|
||||
todo!("generation for exception handling is not implemented");
|
||||
fn handle_error<F: Field>(_state: &mut GenerationState<F>) -> anyhow::Result<()> {
|
||||
bail!("TODO: generation for exception handling is not implemented");
|
||||
}
|
||||
|
||||
pub(crate) fn transition<F: Field>(state: &mut GenerationState<F>) {
|
||||
pub(crate) fn transition<F: Field>(state: &mut GenerationState<F>) -> anyhow::Result<()> {
|
||||
let checkpoint = state.checkpoint();
|
||||
let result = try_perform_instruction(state);
|
||||
|
||||
@ -301,11 +305,12 @@ pub(crate) fn transition<F: Field>(state: &mut GenerationState<F>) {
|
||||
state
|
||||
.memory
|
||||
.apply_ops(state.traces.mem_ops_since(checkpoint.traces));
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
if state.registers.is_kernel {
|
||||
let offset_name = KERNEL.offset_name(state.registers.program_counter);
|
||||
panic!("exception in kernel mode at {}: {:?}", offset_name, e);
|
||||
bail!("exception in kernel mode at {}: {:?}", offset_name, e);
|
||||
}
|
||||
state.rollback(checkpoint);
|
||||
handle_error(state)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user