Increment sender nonce + buy gas

This commit is contained in:
Daniel Lubarov 2023-01-14 22:08:07 -08:00
parent 3a6d693f3f
commit f2e40541d9
7 changed files with 69 additions and 28 deletions

View File

@ -15,10 +15,20 @@ global get_nonce:
%%after: %%after:
%endmacro %endmacro
// Increment the given account's nonce. Assumes the account already exists; panics otherwise.
global increment_nonce: global increment_nonce:
// stack: address, retdest // stack: address, retdest
// TODO: Replace with actual implementation. %mpt_read_state_trie
POP // stack: account_ptr, retdest
DUP1 ISZERO %jumpi(panic)
// stack: nonce_ptr, retdest
DUP1 %mload_trie_data
// stack: nonce, nonce_ptr, retdest
%increment
SWAP1
// stack: nonce_ptr, nonce', retdest
%mstore_trie_data
// stack: retdest
JUMP JUMP
// Convenience macro to call increment_nonce and return where we left off. // Convenience macro to call increment_nonce and return where we left off.

View File

@ -6,22 +6,45 @@
// Pre stack: retdest // Pre stack: retdest
// Post stack: (empty) // Post stack: (empty)
global process_normalized_txn: global process_normalized_txn:
// stack: retdest
PUSH 0 // TODO: Load block's base fee
%mload_txn_field(@TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS)
ADD
// stack: priority_fee + base_fee, retdest
%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
// stack: max_fee, priority_fee + base_fee, retdest
%min
// stack: computed_fee, retdest
%mstore_txn_field(@TXN_FIELD_COMPUTED_FEE_PER_GAS)
// stack: retdest // stack: retdest
PUSH validate PUSH validate
%jump(intrinsic_gas) %jump(intrinsic_gas)
global validate: global validate:
// stack: intrinsic_gas, retdest // stack: intrinsic_gas, retdest
// TODO: Check signature? (Or might happen in type_0.asm etc.)
// TODO: Assert nonce is correct.
// TODO: Assert sender has no code.
POP // TODO: Assert gas_limit >= intrinsic_gas. POP // TODO: Assert gas_limit >= intrinsic_gas.
// stack: retdest // stack: retdest
// TODO: Check that txn nonce matches account nonce.
// TODO: Assert nonce is correct.
// TODO: Assert sender has no code.
// TODO: Assert sender balance >= gas_limit * gas_price + value.
// stack: retdest
global charge_gas: global buy_gas:
// TODO: Deduct gas limit from sender (some gas may be refunded later). %mload_txn_field(@TXN_FIELD_COMPUTED_FEE_PER_GAS)
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
MUL
// stack: gas_cost, retdest
%mload_txn_field(@TXN_FIELD_ORIGIN)
// stack: sender_addr, gas_cost, retdest
%deduct_eth
// stack: deduct_eth_status, retdest
%jumpi(panic)
// stack: retdest
PUSH 0 // TODO: Push sender. global increment_sender_nonce:
%mload_txn_field(@TXN_FIELD_ORIGIN)
%increment_nonce %increment_nonce
global process_based_on_type: global process_based_on_type:
@ -53,6 +76,8 @@ global process_message_txn:
%jumpi(process_message_txn_insufficient_balance) %jumpi(process_message_txn_insufficient_balance)
// stack: retdest // stack: retdest
// TODO: Handle precompiles.
// If to's code is empty, return. // If to's code is empty, return.
%mload_txn_field(@TXN_FIELD_TO) %ext_code_empty %mload_txn_field(@TXN_FIELD_TO) %ext_code_empty
// stack: code_empty, retdest // stack: code_empty, retdest

View File

@ -10,7 +10,6 @@ global transfer_eth:
%jumpi(transfer_eth_failure) %jumpi(transfer_eth_failure)
// stack: to, amount, retdest // stack: to, amount, retdest
%add_eth %add_eth
global transfer_eth_3:
%stack (retdest) -> (retdest, 0) %stack (retdest) -> (retdest, 0)
JUMP JUMP
global transfer_eth_failure: global transfer_eth_failure:
@ -43,7 +42,7 @@ global deduct_eth:
// stack: addr, amount, retdest // stack: addr, amount, retdest
%mpt_read_state_trie %mpt_read_state_trie
// stack: account_ptr, amount, retdest // stack: account_ptr, amount, retdest
DUP1 ISZERO %jumpi(panic) // If the account pointer is null, return 0. DUP1 ISZERO %jumpi(deduct_eth_no_such_account) // If the account pointer is null, return 1.
%add_const(1) %add_const(1)
// stack: balance_ptr, amount, retdest // stack: balance_ptr, amount, retdest
DUP1 %mload_trie_data DUP1 %mload_trie_data
@ -58,6 +57,9 @@ global deduct_eth:
%mstore_trie_data %mstore_trie_data
// stack: retdest, 0 // stack: retdest, 0
JUMP JUMP
global deduct_eth_no_such_account:
%stack (account_ptr, amount, retdest) -> (retdest, 1)
JUMP
global deduct_eth_insufficient_balance: global deduct_eth_insufficient_balance:
%stack (balance, balance_ptr, amount, retdest) -> (retdest, 1) %stack (balance, balance_ptr, amount, retdest) -> (retdest, 1)
JUMP JUMP

View File

@ -5,8 +5,6 @@ pub(crate) enum GlobalMetadata {
/// The largest context ID that has been used so far in this execution. Tracking this allows us /// The largest context ID that has been used so far in this execution. Tracking this allows us
/// give each new context a unique ID, so that its memory will be zero-initialized. /// give each new context a unique ID, so that its memory will be zero-initialized.
LargestContext = 0, LargestContext = 0,
/// The address of the sender of the transaction.
Origin = 1,
/// The size of active memory, in bytes. /// The size of active memory, in bytes.
MemorySize = 2, MemorySize = 2,
/// The size of the `TrieData` segment, in bytes. In other words, the next address available for /// The size of the `TrieData` segment, in bytes. In other words, the next address available for
@ -35,12 +33,11 @@ pub(crate) enum GlobalMetadata {
} }
impl GlobalMetadata { impl GlobalMetadata {
pub(crate) const COUNT: usize = 14; pub(crate) const COUNT: usize = 13;
pub(crate) fn all() -> [Self; Self::COUNT] { pub(crate) fn all() -> [Self; Self::COUNT] {
[ [
Self::LargestContext, Self::LargestContext,
Self::Origin,
Self::MemorySize, Self::MemorySize,
Self::TrieDataSize, Self::TrieDataSize,
Self::StateTrieRoot, Self::StateTrieRoot,
@ -60,7 +57,6 @@ impl GlobalMetadata {
pub(crate) fn var_name(&self) -> &'static str { pub(crate) fn var_name(&self) -> &'static str {
match self { match self {
GlobalMetadata::LargestContext => "GLOBAL_METADATA_LARGEST_CONTEXT", GlobalMetadata::LargestContext => "GLOBAL_METADATA_LARGEST_CONTEXT",
GlobalMetadata::Origin => "GLOBAL_METADATA_ORIGIN",
GlobalMetadata::MemorySize => "GLOBAL_METADATA_MEMORY_SIZE", GlobalMetadata::MemorySize => "GLOBAL_METADATA_MEMORY_SIZE",
GlobalMetadata::TrieDataSize => "GLOBAL_METADATA_TRIE_DATA_SIZE", GlobalMetadata::TrieDataSize => "GLOBAL_METADATA_TRIE_DATA_SIZE",
GlobalMetadata::StateTrieRoot => "GLOBAL_METADATA_STATE_TRIE_ROOT", GlobalMetadata::StateTrieRoot => "GLOBAL_METADATA_STATE_TRIE_ROOT",

View File

@ -9,19 +9,22 @@ pub(crate) enum NormalizedTxnField {
Nonce = 2, Nonce = 2,
MaxPriorityFeePerGas = 3, MaxPriorityFeePerGas = 3,
MaxFeePerGas = 4, MaxFeePerGas = 4,
GasLimit = 5, /// The actual computed gas price for this transaction in the block.
To = 6, /// This is not technically a transaction field, as it depends on the block's base fee.
Value = 7, ComputedFeePerGas = 5,
GasLimit = 6,
To = 7,
Value = 8,
/// The length of the data field. The data itself is stored in another segment. /// The length of the data field. The data itself is stored in another segment.
DataLen = 8, DataLen = 9,
YParity = 9, YParity = 10,
R = 10, R = 11,
S = 11, S = 12,
Origin = 12, Origin = 13,
} }
impl NormalizedTxnField { impl NormalizedTxnField {
pub(crate) const COUNT: usize = 13; pub(crate) const COUNT: usize = 14;
pub(crate) fn all() -> [Self; Self::COUNT] { pub(crate) fn all() -> [Self; Self::COUNT] {
[ [
@ -30,6 +33,7 @@ impl NormalizedTxnField {
Self::Nonce, Self::Nonce,
Self::MaxPriorityFeePerGas, Self::MaxPriorityFeePerGas,
Self::MaxFeePerGas, Self::MaxFeePerGas,
Self::ComputedFeePerGas,
Self::GasLimit, Self::GasLimit,
Self::To, Self::To,
Self::Value, Self::Value,
@ -49,6 +53,7 @@ impl NormalizedTxnField {
NormalizedTxnField::Nonce => "TXN_FIELD_NONCE", NormalizedTxnField::Nonce => "TXN_FIELD_NONCE",
NormalizedTxnField::MaxPriorityFeePerGas => "TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS", NormalizedTxnField::MaxPriorityFeePerGas => "TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS",
NormalizedTxnField::MaxFeePerGas => "TXN_FIELD_MAX_FEE_PER_GAS", NormalizedTxnField::MaxFeePerGas => "TXN_FIELD_MAX_FEE_PER_GAS",
NormalizedTxnField::ComputedFeePerGas => "TXN_FIELD_COMPUTED_FEE_PER_GAS",
NormalizedTxnField::GasLimit => "TXN_FIELD_GAS_LIMIT", NormalizedTxnField::GasLimit => "TXN_FIELD_GAS_LIMIT",
NormalizedTxnField::To => "TXN_FIELD_TO", NormalizedTxnField::To => "TXN_FIELD_TO",
NormalizedTxnField::Value => "TXN_FIELD_VALUE", NormalizedTxnField::Value => "TXN_FIELD_VALUE",

View File

@ -100,8 +100,9 @@ fn test_basic_smart_contract() -> anyhow::Result<()> {
let expected_state_trie_after = { let expected_state_trie_after = {
let sender_account_after = AccountRlp { let sender_account_after = AccountRlp {
balance: sender_account_before.balance - value, // TODO: Also subtract gas_used * price. // TODO: Should be 21k; 1k gas should be refunded.
// nonce: sender_account_before.nonce + 1, // TODO balance: sender_account_before.balance - value - 22_000 * 10,
nonce: sender_account_before.nonce + 1,
..sender_account_before ..sender_account_before
}; };
let to_account_after = AccountRlp { let to_account_after = AccountRlp {
@ -120,6 +121,7 @@ fn test_basic_smart_contract() -> anyhow::Result<()> {
value: rlp::encode(&to_account_after).to_vec(), value: rlp::encode(&to_account_after).to_vec(),
} }
.into(); .into();
// TODO: Beneficiary should receive gas...
PartialTrie::Branch { PartialTrie::Branch {
children, children,
value: vec![], value: vec![],

View File

@ -73,8 +73,9 @@ fn test_simple_transfer() -> anyhow::Result<()> {
let expected_state_trie_after = { let expected_state_trie_after = {
let sender_account_after = AccountRlp { let sender_account_after = AccountRlp {
balance: sender_account_before.balance - value, // TODO: Also subtract gas_used * price. // TODO: Should be 21k; 1k gas should be refunded.
// nonce: sender_account_before.nonce + 1, // TODO balance: sender_account_before.balance - value - 22_000 * 10,
nonce: sender_account_before.nonce + 1,
..sender_account_before ..sender_account_before
}; };
let to_account_after = AccountRlp { let to_account_after = AccountRlp {