Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions executor/evm/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub struct BlockContext {
///
/// Defaults to chainspec `[evm].base_fee * [evm].wei_per_mote`.
pub base_fee: Option<u128>,
pub prevrandao: evm::Hash,
}

impl BlockContext {
Expand All @@ -105,6 +106,7 @@ impl BlockContext {
timestamp: revm::primitives::U256::from(self.timestamp),
gas_limit: self.gas_limit.unwrap_or(config.block_gas_limit),
basefee,
prevrandao: Some(tx::to_revm_hash(self.prevrandao)),
..Default::default()
})
}
Expand All @@ -129,12 +131,17 @@ mod tests {
beneficiary: evm::Address::ZERO,
gas_limit: None,
base_fee: None,
prevrandao: evm::Hash::new([0x42; evm::HASH_LENGTH]),
};
let block = context
.to_revm_block(&config)
.expect("base fee should fit in revm block context");

assert_eq!(u128::from(block.basefee), config.base_fee_wei());
assert_ne!(block.basefee, config.base_fee);
assert_eq!(
block.prevrandao,
Some(revm::primitives::B256::from([0x42; evm::HASH_LENGTH]))
);
}
}
45 changes: 45 additions & 0 deletions executor/evm/tests/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ fn block() -> BlockContext {
beneficiary: evm::Address::ZERO,
gas_limit: None,
base_fee: None,
prevrandao: evm::Hash::new([0x99; evm::HASH_LENGTH]),
}
}

Expand Down Expand Up @@ -168,6 +169,24 @@ fn blockhash_contract_init_code() -> Vec<u8> {
init_code_returning(runtime)
}

fn prevrandao_contract_init_code() -> Vec<u8> {
let runtime = vec![
// bytes32 value = prevrandao();
opcode::DIFFICULTY,
// mstore(0, value);
opcode::PUSH1,
0,
opcode::MSTORE,
// return abi.encode(value);
opcode::PUSH1,
32,
opcode::PUSH1,
0,
opcode::RETURN,
];
init_code_returning(runtime)
}

fn return_word_contract_init_code(value: u8) -> Vec<u8> {
let runtime = vec![
opcode::PUSH1,
Expand Down Expand Up @@ -1799,3 +1818,29 @@ fn checked_calls_enforce_transaction_validation() {
Err(Error::Revm(_))
));
}

#[test]
fn prevrandao_uses_block_context() {
let executor = executor(EvmSpec::Prague);
let from = evm::Address::new([1; 20]);
let (mut tracking_copy, _tempdir) = tracking_copy();
let contract = execute_call(
&executor,
&mut tracking_copy,
from,
None,
prevrandao_contract_init_code(),
)
.created_contract_address
.expect("deploy should return a contract address");

let outcome = execute_call(
&executor,
&mut tracking_copy,
from,
Some(contract),
Vec::new(),
);

assert_eq!(outcome.output.as_slice(), block().prevrandao.as_ref());
}
53 changes: 47 additions & 6 deletions node/src/components/contract_runtime/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use casper_types::{
bytesrepr::{self, Bytes, ToBytes, U32_SERIALIZED_LENGTH},
contracts::NamedKeys,
evm::{
Address as EvmAddress, HaltReason as EvmHaltReason, Receipt as EvmReceipt,
Address as EvmAddress, HaltReason as EvmHaltReason, Hash as EvmHash, Receipt as EvmReceipt,
ReceiptStatus as EvmReceiptStatus,
},
execution::{Effects, ExecutionResult, TransformKindV2, TransformV2},
Expand Down Expand Up @@ -81,13 +81,15 @@ fn evm_block_context(
block_height: u64,
block_time: BlockTime,
proposer: &PublicKey,
prevrandao: EvmHash,
) -> EvmBlockContext {
EvmBlockContext {
number: block_height,
timestamp: block_time.value() / 1000,
beneficiary: EvmAddress::from_block_proposer_public_key(proposer),
gas_limit: Some(chainspec.evm_config.block_gas_limit),
base_fee: Some(chainspec.evm_config.base_fee_wei()),
prevrandao,
}
}

Expand Down Expand Up @@ -684,12 +686,14 @@ pub fn execute_finalized_block(
}
}

let prevrandao =
EvmHash::new(Digest::hash_pair(parent_seed, [executable_block.random_bit as u8]).value());
state_root_hash = write_eip4788_beacon_roots(
&scratch_state,
state_root_hash,
chainspec,
protocol_version,
evm_block_context(chainspec, block_height, block_time, &proposer),
evm_block_context(chainspec, block_height, block_time, &proposer, prevrandao),
parent_hash,
)?;

Expand Down Expand Up @@ -1188,8 +1192,16 @@ pub fn execute_finalized_block(
_ if is_evm => {
let evm_transaction = evm_transaction.expect("EVM transaction should exist");
let base_fee_wei = chainspec.evm_config.base_fee_wei();
let block_context =
evm_block_context(chainspec, block_height, block_time, &proposer);
let random_bit = executable_block.random_bit;
let prevrandao =
EvmHash::new(Digest::hash_pair(parent_seed, [random_bit as u8]).value());
let block_context = evm_block_context(
chainspec,
block_height,
block_time,
&proposer,
prevrandao,
);
let request = EvmExecuteRequest {
block: block_context,
kind: EvmExecuteKind::Transaction(Box::new(evm_transaction.clone())),
Expand Down Expand Up @@ -2169,6 +2181,7 @@ where
beneficiary: EvmAddress::ZERO,
gas_limit: Some(chainspec.evm_config.block_gas_limit),
base_fee: Some(base_fee_wei),
prevrandao: EvmHash::new(block_header.accumulated_seed().value()),
};
let kind = if evm_transaction.is_unsigned_call() {
EvmExecuteKind::Call(EvmExecutorCallRequest {
Expand Down Expand Up @@ -2345,7 +2358,7 @@ pub(crate) fn compute_execution_results_checksum<'a>(
mod tests {
use super::*;
use casper_storage::{global_state::state, tracking_copy::TrackingCopyExt};
use casper_types::{EvmConfig, DEFAULT_WEI_PER_MOTE};
use casper_types::{EvmConfig, Timestamp, DEFAULT_WEI_PER_MOTE};

#[test]
fn should_not_raise_evm_min_cost_above_converted_fee() {
Expand Down Expand Up @@ -2388,7 +2401,8 @@ mod tests {
state::lmdb::make_temporary_global_state([]);
let scratch_state = global_state.create_scratch();
let block_time = BlockTime::new(2_000);
let block_context = evm_block_context(&chainspec, 1, block_time, &PublicKey::System);
let block_context =
evm_block_context(&chainspec, 1, block_time, &PublicKey::System, EvmHash::ZERO);
let parent_hash = BlockHash::new(Digest::from_raw([0x44; 32]));

let updated_state_root_hash = write_eip4788_beacon_roots(
Expand All @@ -2410,4 +2424,31 @@ mod tests {

assert_eq!(entry, Some((block_context.timestamp, parent_hash)));
}

#[test]
fn evm_prevrandao_matches_current_block_accumulated_seed() {
let parent_hash = BlockHash::new(Digest::from_raw([0x11; Digest::LENGTH]));
let parent_seed = Digest::from_raw([0x22; Digest::LENGTH]);
let state_root_hash = Digest::from_raw([0x33; Digest::LENGTH]);
let random_bit = true;
let block = BlockV2::new(
parent_hash,
parent_seed,
state_root_hash,
random_bit,
None,
Timestamp::zero(),
EraId::new(1),
1,
ProtocolVersion::V2_0_0,
PublicKey::System,
BTreeMap::new(),
Default::default(),
1,
None,
);

let prevrandao = EvmHash::new(Digest::hash_pair(parent_seed, [random_bit as u8]).value());
assert_eq!(prevrandao.as_ref(), block.accumulated_seed().as_ref());
}
}
Loading