diff --git a/evm/src/cpu/kernel/asm/core/gas.asm b/evm/src/cpu/kernel/asm/core/gas.asm index ad2966a5..436ccb3e 100644 --- a/evm/src/cpu/kernel/asm/core/gas.asm +++ b/evm/src/cpu/kernel/asm/core/gas.asm @@ -15,8 +15,36 @@ global sys_gas: %mload_context_metadata(@CTX_METADATA_GAS_LIMIT) %endmacro -// Charge gas. Faults if we exceed the limit for the current context. + +// TODO: `%refund_gas` and `refund_gas_hook` are hooks used for debugging. They should be removed at some point and `refund_gas_original` renamed to `refund_gas`. +%macro refund_gas + PUSH %%after %jump(refund_gas_hook) +%%after: + %refund_gas_original +%endmacro + +global refund_gas_hook: + JUMP + +%macro refund_gas_original + // stack: amount + %mload_global_metadata(@GLOBAL_METADATA_REFUND_COUNTER) + ADD + %mstore_global_metadata(@GLOBAL_METADATA_REFUND_COUNTER) +%endmacro + +// TODO: `%charge_gas` and `charge_gas_hook` are hooks used for debugging. They should be removed at some point and `charge_gas_original` renamed to `charge_gas`. %macro charge_gas + PUSH %%after %jump(charge_gas_hook) +%%after: + %charge_gas_original +%endmacro + +global charge_gas_hook: + JUMP + +// Charge gas. Faults if we exceed the limit for the current context. +%macro charge_gas_original // stack: gas, kexit_info %shl_const(192) ADD diff --git a/evm/src/cpu/kernel/asm/core/process_txn.asm b/evm/src/cpu/kernel/asm/core/process_txn.asm index a7ccf864..97d9b8c5 100644 --- a/evm/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm/src/cpu/kernel/asm/core/process_txn.asm @@ -278,7 +278,7 @@ global process_message_txn_after_call: // stack: used_gas, leftover_gas %mload_global_metadata(@GLOBAL_METADATA_REFUND_COUNTER) // stack: refund, used_gas, leftover_gas - DUP2 %div_const(2) // max_refund = used_gas/2 + DUP2 %div_const(@MAX_REFUND_QUOTIENT) // max_refund = used_gas/5 // stack: max_refund, refund, used_gas, leftover_gas %min %stack (refund, used_gas, leftover_gas) -> (leftover_gas, refund, refund, used_gas) diff --git a/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm b/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm index af8bc912..6383b871 100644 --- a/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm +++ b/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm @@ -35,9 +35,54 @@ sstore_warm: %add_const(@GAS_WARMACCESS) sstore_charge_gas: - %stack (gas, original_value, current_value, kexit_info, slot, value) -> (gas, kexit_info, current_value, slot, value) + %stack (gas, original_value, current_value, kexit_info, slot, value) -> (gas, kexit_info, current_value, value, original_value, slot) %charge_gas +sstore_refund: + %stack (kexit_info, current_value, value, original_value, slot) -> (current_value, value, current_value, value, original_value, slot, kexit_info) + EQ %jumpi(sstore_no_refund) + %stack (current_value, value, original_value, slot, kexit_info) -> (current_value, original_value, current_value, value, original_value, slot, kexit_info) + EQ %jumpi(sstore_refund_original) + %stack (current_value, value, original_value, slot, kexit_info) -> (original_value, current_value, value, original_value, slot, kexit_info) + ISZERO %jumpi(sstore_dirty_reset) + %stack (current_value, value, original_value, slot, kexit_info) -> (current_value, current_value, value, original_value, slot, kexit_info) + ISZERO %jumpi(sstore_dirty_clear1) + %stack (current_value, value, original_value, slot, kexit_info) -> (value, current_value, value, original_value, slot, kexit_info) + ISZERO %jumpi(sstore_dirty_clear2) + %jump(sstore_dirty_reset) + +sstore_dirty_clear1: + PUSH @REFUND_SCLEAR PUSH 0 SUB %refund_gas + %jump(sstore_dirty_reset) + +sstore_dirty_clear2: + PUSH @REFUND_SCLEAR %refund_gas + +sstore_dirty_reset: + %stack (current_value, value, original_value, slot, kexit_info) -> (original_value, value, current_value, value, original_value, slot, kexit_info) + EQ %jumpi(sstore_dirty_reset2) + %jump(sstore_no_refund) +sstore_dirty_reset2: + %stack (current_value, value, original_value, slot, kexit_info) -> (original_value, current_value, value, original_value, slot, kexit_info) + ISZERO %jumpi(sstore_dirty_reset_sset) + PUSH @GAS_WARMACCESS PUSH @GAS_SRESET SUB %refund_gas + %jump(sstore_no_refund) +sstore_dirty_reset_sset: + PUSH @GAS_WARMACCESS PUSH @GAS_SSET SUB %refund_gas + %jump(sstore_no_refund) + +sstore_refund_original: + %stack (current_value, value, original_value, slot, kexit_info) -> (value, current_value, value, original_value, slot, kexit_info) + ISZERO %jumpi(sstore_sclear) + %jump(sstore_no_refund) +sstore_sclear: + PUSH @REFUND_SCLEAR %refund_gas + %jump(sstore_no_refund) + +sstore_no_refund: + %stack (current_value, value, original_value, slot, kexit_info) -> (kexit_info, current_value, slot, value) +sstore_after_refund: + // stack: kexit_info, current_value, slot, value // Check if `value` is equal to `current_value`, and if so exit the kernel early. %stack (kexit_info, current_value, slot, value) -> (value, current_value, slot, value, kexit_info) EQ %jumpi(sstore_noop) diff --git a/evm/src/cpu/kernel/constants/mod.rs b/evm/src/cpu/kernel/constants/mod.rs index b1486589..e8489650 100644 --- a/evm/src/cpu/kernel/constants/mod.rs +++ b/evm/src/cpu/kernel/constants/mod.rs @@ -32,6 +32,10 @@ pub fn evm_constants() -> HashMap { c.insert(name.into(), U256::from(value)); } + for (name, value) in REFUND_CONSTANTS { + c.insert(name.into(), U256::from(value)); + } + for (name, value) in PRECOMPILES { c.insert(name.into(), U256::from(value)); } @@ -175,7 +179,7 @@ const EC_CONSTANTS: [(&str, [u8; 32]); 20] = [ ), ]; -const GAS_CONSTANTS: [(&str, u16); 38] = [ +const GAS_CONSTANTS: [(&str, u16); 36] = [ ("GAS_ZERO", 0), ("GAS_JUMPDEST", 1), ("GAS_BASE", 2), @@ -192,8 +196,6 @@ const GAS_CONSTANTS: [(&str, u16); 38] = [ ("GAS_COLDSLOAD_MINUS_WARMACCESS", 2_000), ("GAS_SSET", 20_000), ("GAS_SRESET", 2_900), - ("REFUND_SCLEAR", 15_000), - ("REFUND_SELFDESTRUCT", 24_000), ("GAS_SELFDESTRUCT", 5_000), ("GAS_CREATE", 32_000), ("GAS_CODEDEPOSIT", 200), @@ -216,6 +218,8 @@ const GAS_CONSTANTS: [(&str, u16); 38] = [ ("GAS_BLOCKHASH", 20), ]; +const REFUND_CONSTANTS: [(&str, u16); 2] = [("REFUND_SCLEAR", 4_800), ("MAX_REFUND_QUOTIENT", 5)]; + const PRECOMPILES: [(&str, u16); 9] = [ ("ECREC", 1), ("SHA256", 2),