Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion bus-mapping/src/evm/opcodes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Definition of each opcode of the EVM.
mod coinbase;
mod dup;
pub mod ids;
mod jump;
Expand All @@ -22,6 +23,7 @@ use ids::OpcodeId;
use log::warn;

use self::push::Push;
use coinbase::Coinbase;
use dup::Dup;
use jump::Jump;
use jumpdest::Jumpdest;
Expand Down Expand Up @@ -110,7 +112,7 @@ impl OpcodeId {
// OpcodeId::RETURNDATACOPY => {},
// OpcodeId::EXTCODEHASH => {},
// OpcodeId::BLOCKHASH => {},
// OpcodeId::COINBASE => {},
OpcodeId::COINBASE => Coinbase::gen_associated_ops,
// OpcodeId::TIMESTAMP => {},
// OpcodeId::NUMBER => {},
// OpcodeId::DIFFICULTY => {},
Expand Down
93 changes: 93 additions & 0 deletions bus-mapping/src/evm/opcodes/coinbase.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use super::Opcode;
use crate::circuit_input_builder::CircuitInputStateRef;
use crate::eth_types::GethExecStep;
use crate::{operation::RW, Error};

/// Placeholder structure used to implement [`Opcode`] trait over it
/// corresponding to the [`OpcodeId::PC`](crate::evm::OpcodeId::PC) `OpcodeId`.
#[derive(Debug, Copy, Clone)]
pub(crate) struct Coinbase;

impl Opcode for Coinbase {
fn gen_associated_ops(
state: &mut CircuitInputStateRef,
steps: &[GethExecStep],
) -> Result<(), Error> {
let step = &steps[0];
// Get value result from next step and do stack write
let value = steps[1].stack.last()?;
state.push_stack_op(
RW::WRITE,
step.stack.last_filled().map(|a| a - 1),
value,
);

Ok(())
}
}

#[cfg(test)]
mod coinbase_tests {
use super::*;
use crate::{
bytecode,
circuit_input_builder::{ExecStep, TransactionContext},
eth_types::ToWord,
evm::StackAddress,
mock,
};
use pretty_assertions::assert_eq;

#[test]
fn coinbase_opcode_impl() -> Result<(), Error> {
let code = bytecode! {
// PUSH1(0x1)
Comment thread
DreamWuGit marked this conversation as resolved.
Outdated
// PUSH1(0x2)
#[start]
COINBASE
STOP
};

// Get the execution steps from the external tracer
let block =
mock::BlockData::new_single_tx_trace_code_at_start(&code).unwrap();

let mut builder = block.new_circuit_input_builder();
builder.handle_tx(&block.eth_tx, &block.geth_trace).unwrap();

let mut test_builder = block.new_circuit_input_builder();
let mut tx = test_builder.new_tx(&block.eth_tx).unwrap();
let mut tx_ctx = TransactionContext::new(&block.eth_tx);

// Generate step corresponding to COINBASE
let mut step = ExecStep::new(
&block.geth_trace.struct_logs[0],
0,
test_builder.block_ctx.rwc,
0,
);
let mut state_ref =
test_builder.state_ref(&mut tx, &mut tx_ctx, &mut step);

// Add the last Stack write
state_ref.push_stack_op(
RW::WRITE,
StackAddress::from(1024 - 1),
block.ctants.coinbase.to_word(),
);

tx.steps_mut().push(step);
test_builder.block.txs_mut().push(tx);

// Compare first step bus mapping instance
assert_eq!(
builder.block.txs()[0].steps()[0].bus_mapping_instance,
test_builder.block.txs()[0].steps()[0].bus_mapping_instance,
);

// Compare containers
assert_eq!(builder.block.container, test_builder.block.container);

Ok(())
}
}