diff --git a/evm_loader/lib/src/commands/get_holder.rs b/evm_loader/lib/src/commands/get_holder.rs index fd7ae2d28..4fe77e84e 100644 --- a/evm_loader/lib/src/commands/get_holder.rs +++ b/evm_loader/lib/src/commands/get_holder.rs @@ -46,6 +46,8 @@ pub struct GetHolderResponse { #[serde_as(as = "Option>")] pub accounts: Option>, + + pub steps_executed: u64, } impl GetHolderResponse { @@ -119,6 +121,7 @@ pub fn read_holder(program_id: &Pubkey, info: AccountInfo) -> NeonResult Err(ProgramError::InvalidAccountData.into()), diff --git a/evm_loader/program/src/account/state.rs b/evm_loader/program/src/account/state.rs index 0c6184f84..b27a904ff 100644 --- a/evm_loader/program/src/account/state.rs +++ b/evm_loader/program/src/account/state.rs @@ -33,6 +33,8 @@ struct Data { /// Ethereum transaction gas used and paid #[serde(with = "ethnum::serde::bytes::le")] pub gas_used: U256, + /// Steps executed in the transaction + pub steps_executed: u64, } #[repr(C, packed)] @@ -112,6 +114,7 @@ impl<'a> StateAccount<'a> { origin, revisions, gas_used: U256::ZERO, + steps_executed: 0_u64, }; super::set_tag(program_id, &info, TAG_STATE, Header::VERSION)?; @@ -289,4 +292,23 @@ impl<'a> StateAccount<'a> { let unused_gas = self.gas_available(); self.consume_gas(unused_gas, origin) } + + #[must_use] + pub fn steps_executed(&self) -> u64 { + self.data.steps_executed + } + + pub fn reset_steps_executed(&mut self) { + self.data.steps_executed = 0; + } + + pub fn increment_steps_executed(&mut self, steps: u64) -> Result<()> { + self.data.steps_executed = self + .data + .steps_executed + .checked_add(steps) + .ok_or(Error::IntegerOverflow)?; + + Ok(()) + } } diff --git a/evm_loader/program/src/instruction/transaction_execute.rs b/evm_loader/program/src/instruction/transaction_execute.rs index 85dbed504..cf790ae97 100644 --- a/evm_loader/program/src/instruction/transaction_execute.rs +++ b/evm_loader/program/src/instruction/transaction_execute.rs @@ -25,17 +25,23 @@ pub fn execute( account_storage.origin(origin, &trx)?.increment_nonce()?; - let (exit_reason, apply_state) = { + let (exit_reason, apply_state, steps_executed) = { let mut backend = ExecutorState::new(&account_storage); let mut evm = Machine::new(&trx, origin, &mut backend, None::)?; - let (result, _, _) = evm.execute(u64::MAX, &mut backend)?; + let (result, steps_executed, _) = evm.execute(u64::MAX, &mut backend)?; let actions = backend.into_actions(); - (result, actions) + (result, actions, steps_executed) }; + log_data(&[ + b"STEPS", + &steps_executed.to_le_bytes(), // Iteration steps + &steps_executed.to_le_bytes(), // Total steps is the same as iteration steps + ]); + let allocate_result = account_storage.allocate(&apply_state)?; if allocate_result != AllocateResult::Ready { return Err(Error::AccountSpaceAllocationFailure); diff --git a/evm_loader/program/src/instruction/transaction_step.rs b/evm_loader/program/src/instruction/transaction_step.rs index aa377f6db..ca56888bb 100644 --- a/evm_loader/program/src/instruction/transaction_step.rs +++ b/evm_loader/program/src/instruction/transaction_step.rs @@ -62,6 +62,8 @@ pub fn do_continue<'a>( let account_storage = ProgramAccountStorage::new(accounts)?; let (mut backend, mut evm) = if reset { + storage.reset_steps_executed(); + let mut backend = ExecutorState::new(&account_storage); let evm = Machine::new(storage.trx(), storage.trx_origin(), &mut backend, None)?; (backend, evm) @@ -98,6 +100,13 @@ fn finalize<'a>( ) -> Result<()> { debug_print!("finalize"); + storage.increment_steps_executed(steps_executed)?; + log_data(&[ + b"STEPS", + &steps_executed.to_le_bytes(), + &storage.steps_executed().to_le_bytes(), + ]); + if steps_executed > 0 { accounts.transfer_treasury_payment()?; }