Skip to content
This repository was archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #4 from clabby/cl/auth-stuff
Browse files Browse the repository at this point in the history
feat: `AUTH` updates
  • Loading branch information
clabby authored Dec 2, 2023
2 parents 1d06742 + 2a00a1e commit 68e0dd7
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 24 deletions.
3 changes: 3 additions & 0 deletions crates/interpreter/src/gas/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ pub const WARM_STORAGE_READ_COST: u64 = 100;
pub const INITCODE_WORD_COST: u64 = 2;

pub const CALL_STIPEND: u64 = 2300;

// EIP-3074: AUTH and AUTHCALL
pub const AUTH: u64 = 3100;
4 changes: 4 additions & 0 deletions crates/interpreter/src/instruction_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub enum InstructionResult {
OpcodeNotFound,
CallNotAllowedInsideStatic,
StateChangeDuringStaticCall,
ActiveAccountUnsetAuthCall,
InvalidFEOpcode,
InvalidJump,
NotActivated,
Expand Down Expand Up @@ -169,6 +170,9 @@ impl From<InstructionResult> for SuccessOrHalt {
InstructionResult::StateChangeDuringStaticCall => {
Self::Halt(Halt::StateChangeDuringStaticCall)
}
InstructionResult::ActiveAccountUnsetAuthCall => {
Self::Halt(Halt::ActiveAccountUnsetAuthCall)
}
InstructionResult::InvalidFEOpcode => Self::Halt(Halt::InvalidFEOpcode),
InstructionResult::InvalidJump => Self::Halt(Halt::InvalidJump),
InstructionResult::NotActivated => Self::Halt(Halt::NotActivated),
Expand Down
61 changes: 40 additions & 21 deletions crates/interpreter/src/instructions/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,11 +373,17 @@ pub fn auth<H: Host, SPEC: Spec>(interpreter: &mut Interpreter<'_>, host: &mut H
// Pop the signature offset and length off of the stack
pop!(interpreter, signature_offset, signature_len);

// Grab the memory region for the input data
let mem_slice = interpreter.shared_memory.slice(
signature_offset.try_into().unwrap_or_default(),
signature_len.try_into().unwrap_or_default(),
);
let signature_offset = as_usize_or_fail!(interpreter, signature_offset);
let signature_len = as_usize_or_fail!(interpreter, signature_len);

// Charge the fixed cost for the `AUTH` opcode
gas!(interpreter, gas::AUTH);

// Grab the memory region for the input data and charge for any memory expansion
shared_memory_resize!(interpreter, signature_offset, signature_len);
let mem_slice = interpreter
.shared_memory
.slice(signature_offset, signature_len);

// Pull the signature from the first 65 bytes of the memory region.
let signature = {
Expand All @@ -398,14 +404,15 @@ pub fn auth<H: Host, SPEC: Spec>(interpreter: &mut Interpreter<'_>, host: &mut H
});

// Build the original auth message and compute the hash.
let mut message = [0u8; 96];
message[0..32].copy_from_slice(
let mut message = [0u8; 97];
message[0] = 0x03; // AUTH_MAGIC
message[1..33].copy_from_slice(
U256::from(host.env().cfg.chain_id)
.to_be_bytes::<32>()
.as_ref(),
);
message[32..64].copy_from_slice(interpreter.contract().address.into_word().as_ref());
message[64..96].copy_from_slice(commit.unwrap_or_default().as_ref());
message[33..65].copy_from_slice(interpreter.contract().address.into_word().as_ref());
message[65..97].copy_from_slice(commit.unwrap_or_default().as_ref());
let message_hash = revm_primitives::keccak256(&message);

// Verify the signature
Expand All @@ -415,7 +422,7 @@ pub fn auth<H: Host, SPEC: Spec>(interpreter: &mut Interpreter<'_>, host: &mut H
push!(interpreter, U256::ZERO);
} else {
push!(interpreter, U256::from(1));
// TODO: Set `authorized` context.
interpreter.active_account = Some(authority);
}
}

Expand Down Expand Up @@ -454,15 +461,14 @@ fn prepare_call_inputs<H: Host, SPEC: Spec>(
CallScheme::AuthCall => {
pop!(interpreter, value);
value
},
}
};

if scheme == CallScheme::AuthCall {
pop!(interpreter, ext_value);
// ext_value must be 0 or it reverts
// If `ext_value` is non-zero, then the `AUTHCALL` opcode immediately returns 0.
if ext_value != U256::ZERO {
// TODO: new InstructionResult enum
interpreter.instruction_result = InstructionResult::FatalExternalError;
push!(interpreter, U256::ZERO);
return;
}
};
Expand Down Expand Up @@ -510,13 +516,17 @@ fn prepare_call_inputs<H: Host, SPEC: Spec>(
scheme,
},
CallScheme::AuthCall => {
CallContext {
address: interpreter.contract.address,
// TODO: Should be auth caller, need context var
caller: interpreter.contract.caller,
code_address: to,
apparent_value: interpreter.contract.value, // TODO: Prob not correct, check spec
scheme,
if let Some(account) = interpreter.active_account {
CallContext {
address: interpreter.contract.address,
caller: account,
code_address: to,
apparent_value: value,
scheme,
}
} else {
interpreter.instruction_result = InstructionResult::ActiveAccountUnsetAuthCall;
return;
}
}
};
Expand All @@ -533,6 +543,12 @@ fn prepare_call_inputs<H: Host, SPEC: Spec>(
target: interpreter.contract.address,
value,
}
} else if scheme == CallScheme::AuthCall {
Transfer {
source: interpreter.active_account.unwrap_or_default(),
target: to,
value,
}
} else {
//this is dummy send for StaticCall and DelegateCall, it should do nothing and dont touch anything.
Transfer {
Expand All @@ -549,6 +565,7 @@ fn prepare_call_inputs<H: Host, SPEC: Spec>(
};
let is_new = !exist;

// TODO(clabby): EIP-3074 - AuthCall needs coverage
gas!(
interpreter,
gas::call_cost::<SPEC>(
Expand Down Expand Up @@ -597,6 +614,8 @@ pub fn call_inner<SPEC: Spec, H: Host>(
CallScheme::DelegateCall => check!(interpreter, HOMESTEAD),
// EIP-214: New opcode STATICCALL
CallScheme::StaticCall => check!(interpreter, BYZANTIUM),
// EIP-3074: New opcode AUTHCALL
CallScheme::AuthCall => check!(interpreter, PRAGUE),
_ => (),
}
interpreter.return_data_buffer = Bytes::new();
Expand Down
5 changes: 3 additions & 2 deletions crates/interpreter/src/instructions/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -834,8 +834,8 @@ const fn opcode_gas_info(opcode: u8, spec: SpecId) -> OpInfo {
RETURN => OpInfo::gas_block_end(0),
DELEGATECALL => OpInfo::gas_block_end(0),
CREATE2 => OpInfo::gas_block_end(0),
0xF6 => OpInfo::none(),
0xF7 => OpInfo::none(),
AUTH => OpInfo::dynamic_gas(),
AUTHCALL => OpInfo::gas_block_end(0), // TODO: Reassess once AUTHCALL is impl'd
0xF8 => OpInfo::none(),
0xF9 => OpInfo::none(),
STATICCALL => OpInfo::gas_block_end(0),
Expand Down Expand Up @@ -911,6 +911,7 @@ pub const fn spec_opcode_gas(spec_id: SpecId) -> &'static [OpInfo; 256] {
MERGE,
SHANGHAI,
CANCUN,
PRAGUE,
LATEST,
)
}
4 changes: 4 additions & 0 deletions crates/interpreter/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod stack;

pub use analysis::BytecodeLocked;
pub use contract::Contract;
use revm_primitives::Address;
pub use shared_memory::{next_multiple_of_32, SharedMemory};
pub use stack::{Stack, STACK_LIMIT};

Expand Down Expand Up @@ -45,6 +46,8 @@ pub struct Interpreter<'a> {
pub return_len: usize,
/// Whether the interpreter is in "staticcall" mode, meaning no state changes can happen.
pub is_static: bool,
/// EIP-3074: Active account for `AUTHCALL` instructions in the current execution frame.
pub active_account: Option<Address>,
}

impl<'a> Interpreter<'a> {
Expand All @@ -66,6 +69,7 @@ impl<'a> Interpreter<'a> {
return_offset: 0,
shared_memory,
stack: Stack::new(),
active_account: None,
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/precompile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl SpecId {
BYZANTIUM | CONSTANTINOPLE | PETERSBURG => Self::BYZANTIUM,
ISTANBUL | MUIR_GLACIER => Self::ISTANBUL,
BERLIN | LONDON | ARROW_GLACIER | GRAY_GLACIER | MERGE | SHANGHAI => Self::BERLIN,
CANCUN => Self::CANCUN,
CANCUN | PRAGUE => Self::CANCUN,
LATEST => Self::LATEST,
#[cfg(feature = "optimism")]
BEDROCK | REGOLITH | CANYON => Self::BERLIN,
Expand Down
1 change: 1 addition & 0 deletions crates/primitives/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ pub enum Halt {
/* Internal Halts that can be only found inside Inspector */
OverflowPayment,
StateChangeDuringStaticCall,
ActiveAccountUnsetAuthCall,
CallNotAllowedInsideStatic,
OutOfFund,
CallTooDeep,
Expand Down
4 changes: 4 additions & 0 deletions crates/primitives/src/specification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub enum SpecId {
MERGE = 15, // Paris/Merge 15537394 (TTD: 58750000000000000000000)
SHANGHAI = 16, // Shanghai 17034870 (TS: 1681338455)
CANCUN = 17, // Cancun TBD
PRAGUE = 18, // Prague TBD
LATEST = u8::MAX,
}

Expand Down Expand Up @@ -60,6 +61,7 @@ pub enum SpecId {
SHANGHAI = 18,
CANYON = 19,
CANCUN = 20,
PRAGUE = 21,
LATEST = u8::MAX,
}

Expand Down Expand Up @@ -92,6 +94,7 @@ impl From<&str> for SpecId {
"Merge" => Self::MERGE,
"Shanghai" => Self::SHANGHAI,
"Cancun" => Self::CANCUN,
"Prague" => Self::PRAGUE,
#[cfg(feature = "optimism")]
"Bedrock" => SpecId::BEDROCK,
#[cfg(feature = "optimism")]
Expand Down Expand Up @@ -143,6 +146,7 @@ spec!(LONDON, LondonSpec);
spec!(MERGE, MergeSpec);
spec!(SHANGHAI, ShanghaiSpec);
spec!(CANCUN, CancunSpec);
spec!(PRAGUE, PragueSpec);
spec!(LATEST, LatestSpec);

// Optimism Hardforks
Expand Down
1 change: 1 addition & 0 deletions crates/revm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ pub fn evm_inner<'a, DB: Database>(
SpecId::MERGE => create_evm!(MergeSpec),
SpecId::SHANGHAI => create_evm!(ShanghaiSpec),
SpecId::CANCUN => create_evm!(CancunSpec),
SpecId::PRAGUE => create_evm!(PragueSpec),
SpecId::LATEST => create_evm!(LatestSpec),
#[cfg(feature = "optimism")]
SpecId::BEDROCK => create_evm!(BedrockSpec),
Expand Down

0 comments on commit 68e0dd7

Please sign in to comment.