mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 07:13:08 +00:00
Contract creation fixes
This commit is contained in:
parent
893b88c309
commit
afded1682b
@ -43,4 +43,4 @@ global sys_selfbalance:
|
||||
%address
|
||||
%jump(balance)
|
||||
%%after:
|
||||
%endmacro
|
||||
%endmacro
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
// TODO: This file needs to be cleaned up.
|
||||
// `create` is no longer being used for contract-creation txns,
|
||||
// so it can be inlined. Also need to set metadata on new ctx.
|
||||
|
||||
// The CREATE syscall.
|
||||
//
|
||||
// Pre stack: kexit_info, value, code_offset, code_len
|
||||
@ -24,8 +28,8 @@ sys_create_finish:
|
||||
// Note: CODE_ADDR refers to a (context, segment, offset) tuple.
|
||||
global create:
|
||||
// stack: sender, endowment, CODE_ADDR, code_len, retdest
|
||||
// TODO: Charge gas.
|
||||
DUP1 %get_nonce
|
||||
DUP1 %nonce
|
||||
|
||||
// stack: nonce, sender, endowment, CODE_ADDR, code_len, retdest
|
||||
// Call get_create_address and have it return to create_inner.
|
||||
%stack (nonce, sender)
|
||||
@ -67,12 +71,14 @@ sys_create2_finish:
|
||||
// Pre stack: address, sender, endowment, CODE_ADDR, code_len, retdest
|
||||
// Post stack: address
|
||||
// Note: CODE_ADDR refers to a (context, segment, offset) tuple.
|
||||
create_inner:
|
||||
global create_inner:
|
||||
// stack: address, sender, endowment, CODE_ADDR, code_len, retdest
|
||||
%stack (address, sender, endowment)
|
||||
-> (sender, address, endowment, sender, address)
|
||||
// TODO: Need to handle insufficient balance failure.
|
||||
|
||||
%transfer_eth
|
||||
// stack: transfer_eth_status, sender, address, CODE_ADDR, code_len, retdest
|
||||
%jumpi(fault_exception)
|
||||
// stack: sender, address, CODE_ADDR, code_len, retdest
|
||||
|
||||
%increment_nonce
|
||||
|
||||
@ -5,14 +5,32 @@
|
||||
// Post stack: address
|
||||
global get_create_address:
|
||||
// stack: sender, nonce, retdest
|
||||
// TODO: Replace with actual implementation.
|
||||
%pop2
|
||||
PUSH 123
|
||||
%alloc_rlp_block
|
||||
// stack: rlp_start, sender, nonce, retdest
|
||||
%stack (rlp_start, sender, nonce) -> (rlp_start, sender, nonce, rlp_start)
|
||||
// stack: rlp_start, sender, nonce, rlp_start, retdest
|
||||
%encode_rlp_160 // TODO: or encode_rlp_scalar?
|
||||
// stack: rlp_pos, nonce, rlp_start, retdest
|
||||
%encode_rlp_scalar
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
%prepend_rlp_list_prefix
|
||||
// stack: rlp_prefix_start, rlp_len, retdest
|
||||
PUSH @SEGMENT_RLP_RAW
|
||||
PUSH 0 // context
|
||||
// stack: RLP_ADDR: 3, rlp_len, retdest
|
||||
KECCAK_GENERAL
|
||||
// stack: address, retdest
|
||||
%observe_new_address
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
// Convenience macro to call get_create_address and return where we left off.
|
||||
%macro get_create_address
|
||||
%stack (sender, nonce) -> (sender, nonce, %%after)
|
||||
%jump(get_create_address)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
// Computes the address for a contract based on the CREATE2 rule, i.e.
|
||||
// address = KEC(0xff || sender || salt || code_hash)[12:]
|
||||
//
|
||||
|
||||
@ -1,17 +1,21 @@
|
||||
// Increment the nonce of the given account.
|
||||
// Get the nonce of the given account.
|
||||
// Pre stack: address, retdest
|
||||
// Post stack: (empty)
|
||||
|
||||
global get_nonce:
|
||||
global nonce:
|
||||
// stack: address, retdest
|
||||
// TODO: Replace with actual implementation.
|
||||
POP
|
||||
JUMP
|
||||
%mpt_read_state_trie
|
||||
// stack: account_ptr, retdest
|
||||
// The nonce is the first account field, so we deref the account pointer itself.
|
||||
// Note: We don't need to handle account_ptr=0, as trie_data[0] = 0,
|
||||
// so the deref will give 0 (the default nonce) as desired.
|
||||
%mload_trie_data
|
||||
// stack: nonce, retdest
|
||||
SWAP1 JUMP
|
||||
|
||||
// Convenience macro to call get_nonce and return where we left off.
|
||||
%macro get_nonce
|
||||
// Convenience macro to call nonce and return where we left off.
|
||||
%macro nonce
|
||||
%stack (address) -> (address, %%after)
|
||||
%jump(get_nonce)
|
||||
%jump(nonce)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
@ -20,7 +24,7 @@ global increment_nonce:
|
||||
// stack: address, retdest
|
||||
%mpt_read_state_trie
|
||||
// stack: account_ptr, retdest
|
||||
DUP1 ISZERO %jumpi(panic)
|
||||
DUP1 ISZERO %jumpi(increment_nonce_no_such_account)
|
||||
// stack: nonce_ptr, retdest
|
||||
DUP1 %mload_trie_data
|
||||
// stack: nonce, nonce_ptr, retdest
|
||||
@ -30,6 +34,8 @@ global increment_nonce:
|
||||
%mstore_trie_data
|
||||
// stack: retdest
|
||||
JUMP
|
||||
global increment_nonce_no_such_account:
|
||||
PANIC
|
||||
|
||||
// Convenience macro to call increment_nonce and return where we left off.
|
||||
%macro increment_nonce
|
||||
|
||||
@ -50,23 +50,76 @@ global process_based_on_type:
|
||||
|
||||
global process_contract_creation_txn:
|
||||
// stack: retdest
|
||||
PUSH process_contract_creation_txn_after_create
|
||||
// stack: process_contract_creation_txn_after_create, retdest
|
||||
%mload_txn_field(@TXN_FIELD_DATA_LEN)
|
||||
// stack: code_len, process_contract_creation_txn_after_create, retdest
|
||||
PUSH 0
|
||||
// stack: code_offset, code_len, process_contract_creation_txn_after_create, retdest
|
||||
PUSH @SEGMENT_TXN_DATA
|
||||
// stack: code_segment, code_offset, code_len, process_contract_creation_txn_after_create, retdest
|
||||
PUSH 0 // context
|
||||
// stack: CODE_ADDR, code_len, process_contract_creation_txn_after_create, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_ORIGIN)
|
||||
// stack: origin, retdest
|
||||
DUP1 %nonce
|
||||
// stack: origin_nonce, origin, retdest
|
||||
SWAP1
|
||||
// stack: origin, origin_nonce, retdest
|
||||
%get_create_address
|
||||
// stack: address, retdest
|
||||
|
||||
// Deduct value from caller.
|
||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||
%mload_txn_field(@TXN_FIELD_ORIGIN)
|
||||
// stack: sender, endowment, CODE_ADDR, code_len, process_contract_creation_txn_after_create, retdest
|
||||
%jump(create)
|
||||
%deduct_eth
|
||||
// stack: deduct_eth_status, address, retdest
|
||||
%jumpi(panic)
|
||||
// stack: address, retdest
|
||||
|
||||
global process_contract_creation_txn_after_create:
|
||||
// stack: new_address, retdest
|
||||
// Write the new account's data to MPT data, and get a pointer to it.
|
||||
%get_trie_data_size
|
||||
// stack: account_ptr, address, retdest
|
||||
PUSH 1 %append_to_trie_data // nonce = 1
|
||||
// stack: account_ptr, address, retdest
|
||||
DUP2 %balance %mload_txn_field(@TXN_FIELD_VALUE) ADD %append_to_trie_data // balance = old_balance + txn_value
|
||||
// stack: account_ptr, address, retdest
|
||||
PUSH 0 %append_to_trie_data // storage_root = nil
|
||||
// stack: account_ptr, address, retdest
|
||||
PUSH @EMPTY_STRING_HASH %append_to_trie_data // code_hash = keccak('')
|
||||
// stack: account_ptr, address, retdest
|
||||
DUP2
|
||||
// stack: address, account_ptr, address, retdest
|
||||
%mpt_insert_state_trie
|
||||
// stack: address, retdest
|
||||
|
||||
%create_context
|
||||
// stack: new_ctx, address, retdest
|
||||
|
||||
// Copy the code from txdata to the new context's code segment.
|
||||
PUSH process_contract_creation_txn_after_code_loaded
|
||||
%mload_txn_field(@TXN_FIELD_DATA_LEN)
|
||||
PUSH 0 // SRC.offset
|
||||
PUSH @SEGMENT_TXN_DATA // SRC.segment
|
||||
PUSH 0 // SRC.context
|
||||
PUSH 0 // DST.offset
|
||||
PUSH @SEGMENT_CODE // DST.segment
|
||||
DUP7 // DST.context = new_ctx
|
||||
%jump(memcpy)
|
||||
|
||||
process_contract_creation_txn_after_code_loaded:
|
||||
// stack: new_ctx, address, retdest
|
||||
|
||||
// Each line in the block below does not change the stack.
|
||||
DUP2 %set_new_ctx_addr
|
||||
%mload_txn_field(@TXN_FIELD_ORIGIN) %set_new_ctx_caller
|
||||
%mload_txn_field(@TXN_FIELD_VALUE) %set_new_ctx_value
|
||||
%set_new_ctx_parent_ctx
|
||||
%set_new_ctx_parent_pc(process_contract_creation_txn_after_constructor)
|
||||
%non_intrinisic_gas %set_new_ctx_gas_limit
|
||||
// stack: new_ctx, address, retdest
|
||||
|
||||
%enter_new_ctx
|
||||
// (Old context) stack: new_ctx, address, retdest
|
||||
|
||||
global process_contract_creation_txn_after_constructor:
|
||||
// stack: success, leftover_gas, new_ctx, address, retdest
|
||||
POP // TODO: Success will go into the receipt when we support that.
|
||||
// stack: leftover_gas, new_ctx, address, retdest
|
||||
%pay_coinbase_and_refund_sender
|
||||
// stack: new_ctx, address, retdest
|
||||
POP
|
||||
POP
|
||||
JUMP
|
||||
|
||||
@ -105,9 +158,8 @@ global process_message_txn_insufficient_balance:
|
||||
|
||||
global process_message_txn_return:
|
||||
// stack: retdest
|
||||
%mload_txn_field(@TXN_FIELD_INTRINSIC_GAS)
|
||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
SUB
|
||||
// Since no code was executed, the leftover gas is the non-intrinsic gas.
|
||||
%non_intrinisic_gas
|
||||
// stack: leftover_gas, retdest
|
||||
%pay_coinbase_and_refund_sender
|
||||
// stack: retdest
|
||||
@ -124,18 +176,13 @@ global process_message_txn_code_loaded:
|
||||
%mload_txn_field(@TXN_FIELD_VALUE) %set_new_ctx_value
|
||||
%set_new_ctx_parent_ctx
|
||||
%set_new_ctx_parent_pc(process_message_txn_after_call)
|
||||
// stack: new_ctx, retdest
|
||||
|
||||
// The gas provided to the callee is gas_limit - intrinsic_gas.
|
||||
%mload_txn_field(@TXN_FIELD_INTRINSIC_GAS)
|
||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
SUB
|
||||
%set_new_ctx_gas_limit
|
||||
%non_intrinisic_gas %set_new_ctx_gas_limit
|
||||
// stack: new_ctx, retdest
|
||||
|
||||
// TODO: Copy TXN_DATA to CALLDATA
|
||||
|
||||
%enter_new_ctx
|
||||
// (Old context) stack: new_ctx, retdest
|
||||
|
||||
global process_message_txn_after_call:
|
||||
// stack: success, leftover_gas, new_ctx, retdest
|
||||
@ -206,3 +253,11 @@ global process_message_txn_after_call:
|
||||
%mstore_txn_field(@TXN_FIELD_COMPUTED_PRIORITY_FEE_PER_GAS)
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
%macro non_intrinisic_gas
|
||||
// stack: (empty)
|
||||
%mload_txn_field(@TXN_FIELD_INTRINSIC_GAS)
|
||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
SUB
|
||||
// stack: gas_limit - intrinsic_gas
|
||||
%endmacro
|
||||
|
||||
@ -97,6 +97,15 @@ global terminate_common:
|
||||
%shr_const(192)
|
||||
// stack: gas_used
|
||||
%mload_context_metadata(@CTX_METADATA_GAS_LIMIT)
|
||||
// stack: gas_limit, gas_used
|
||||
SWAP1
|
||||
// stack: gas_used, gas_limit
|
||||
DUP2 DUP2 LT
|
||||
// stack: gas_used < gas_limit, gas_used, gas_limit
|
||||
SWAP2
|
||||
// stack: gas_limit, gas_used, gas_used < gas_limit
|
||||
SUB
|
||||
// stack: leftover_gas
|
||||
// stack: gas_limit - gas_used, gas_used < gas_limit
|
||||
MUL
|
||||
// stack: leftover_gas = (gas_limit - gas_used) * (gas_used < gas_limit)
|
||||
%endmacro
|
||||
|
||||
@ -15,3 +15,9 @@ mpt_insert_state_trie_save:
|
||||
// stack: updated_node_ptr, retdest
|
||||
%mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT)
|
||||
JUMP
|
||||
|
||||
%macro mpt_insert_state_trie
|
||||
%stack (key, value_ptr) -> (key, value_ptr, %%after)
|
||||
%jump(mpt_insert_state_trie)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
@ -102,7 +102,7 @@ type_0_compute_signed_data:
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_TO)
|
||||
SWAP1 %encode_rlp_160
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ethereum_types::{Address, H160, H256, U256};
|
||||
use ethereum_types::{Address, BigEndianHash, H160, H256, U256};
|
||||
use keccak_hash::keccak;
|
||||
use plonky2::field::types::Field;
|
||||
|
||||
@ -72,10 +72,10 @@ impl<F: Field> GenerationState<F> {
|
||||
pub fn jump_to(&mut self, dst: usize) {
|
||||
self.registers.program_counter = dst;
|
||||
if dst == KERNEL.global_labels["observe_new_address"] {
|
||||
let address = stack_peek(self, 0).expect("Empty stack");
|
||||
let mut address_bytes = [0; 20];
|
||||
address.to_big_endian(&mut address_bytes);
|
||||
self.observe_address(H160(address_bytes));
|
||||
let tip_u256 = stack_peek(self, 0).expect("Empty stack");
|
||||
let tip_h256 = H256::from_uint(&tip_u256);
|
||||
let tip_h160 = H160::from(tip_h256);
|
||||
self.observe_address(tip_h160);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user