From cd65490bb2c27075730fb39df42e33e6269f697a Mon Sep 17 00:00:00 2001 From: poltao Date: Fri, 6 Dec 2024 15:09:29 +0800 Subject: [PATCH] feat(zink): add block properties --- evm/opcodes/src/cancun.rs | 2 +- examples/properties.rs | 43 +++++++++++++++++++++++++ zink/src/ffi/evm.rs | 38 +++++++++++++++++----- zink/src/primitives/mod.rs | 1 + zink/src/primitives/properties.rs | 52 +++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 examples/properties.rs create mode 100644 zink/src/primitives/properties.rs diff --git a/evm/opcodes/src/cancun.rs b/evm/opcodes/src/cancun.rs index 43a078cf6..f2d351587 100644 --- a/evm/opcodes/src/cancun.rs +++ b/evm/opcodes/src/cancun.rs @@ -51,7 +51,7 @@ opcodes! { (0x41, COINBASE, 2, 0, 1, "Get the block's beneficiary address.", Frontier, BlockInformation), (0x42, TIMESTAMP, 2, 0, 1, "Get the block's timestamp.", Frontier, BlockInformation), (0x43, NUMBER, 2, 0, 1, "Get the block's number.", Frontier, BlockInformation), - (0x44, DIFFICULTY, 2, 0, 1, "Get the block's difficulty.", Frontier, BlockInformation), + (0x44, PREVRANDAO, 2, 0, 1, "Get the previous block’s RANDAO mix", Frontier, BlockInformation), (0x45, GASLIMIT, 2, 0, 1, "Get the block's gas limit.", Frontier, BlockInformation), (0x46, CHAINID, 2, 0, 1, "Get the chain ID.", Istanbul, BlockInformation), (0x47, SELFBALANCE, 5, 0, 1, "Get balance of currently executing account.", Istanbul, BlockInformation), diff --git a/examples/properties.rs b/examples/properties.rs new file mode 100644 index 000000000..a86972e35 --- /dev/null +++ b/examples/properties.rs @@ -0,0 +1,43 @@ +//! Example for Block and Transaction Properties. +#![cfg_attr(target_arch = "wasm32", no_std)] +#![cfg_attr(target_arch = "wasm32", no_main)] + +extern crate zink; +use zink::primitives::{properties, Bytes32}; + +#[zink::external] +pub fn blockhash(block_number: u64) -> Bytes32 { + properties::blockhash(block_number) +} + +#[zink::external] +pub fn number() -> u64 { + properties::number() +} + +#[cfg(not(target_arch = "wasm32"))] +fn main() {} + +#[test] +fn test_block_properties() -> anyhow::Result<()> { + use zint::{Bytes32, Contract, EVM}; + + let mut evm = EVM::default().commit(true); + let contract = Contract::search("properties")?.compile()?; + let raw_info = evm.deploy(&contract.bytecode()?)?; + + let info = evm + .calldata(&contract.encode(&[b"number()".to_vec()])?) + .call(raw_info.address)?; + assert_eq!(info.ret, 0u64.to_bytes32(), "{info:?}"); + + let info = evm + .calldata(&contract.encode(&[ + b"blockhash(uint64)".to_vec(), + 599423545u64.to_bytes32().to_vec(), + ])?) + .call(raw_info.address)?; + assert_eq!(info.ret, 0u64.to_bytes32(), "{info:?}"); + + Ok(()) +} diff --git a/zink/src/ffi/evm.rs b/zink/src/ffi/evm.rs index b543644b8..e775756bd 100644 --- a/zink/src/ffi/evm.rs +++ b/zink/src/ffi/evm.rs @@ -1,6 +1,6 @@ //! EVM FFI. -use crate::primitives::Address; +use crate::primitives::{Address, Bytes32}; #[link(wasm_import_module = "evm")] #[allow(improper_ctypes)] @@ -134,12 +134,6 @@ extern "C" { /// Get the current message sender pub fn caller() -> Address; - /// Get the current blob hash at index - pub fn blobhash(); - - /// Get the current blob base fee - pub fn blobbasefee(); - /// Append log record with no topics pub fn log0(name: &'static [u8]); @@ -165,4 +159,34 @@ extern "C" { topic3: &'static [u8], topic4: &'static [u8], ); + + /// Get the current block number. + pub fn number() -> u64; + + /// Get the hash of one of the 256 most recent complete blocks. + pub fn blockhash(block_number: u64) -> Bytes32; + + /// Get versioned hashes. + pub fn blobhash(index: u64) -> Bytes32; + + /// Get the current block’s base fee. + pub fn basefee() -> u64; + + /// Get the current block’s blob base fee. + pub fn blobbasefee() -> u64; + + /// Get the current chain id. + pub fn chainid() -> u64; + + /// Get the block’s beneficiary address. + pub fn coinbase() -> Address; + + /// Get the previous block’s RANDAO mix. + pub fn prevrandao() -> Bytes32; + + /// Get the current block gaslimit. + pub fn gaslimit() -> u64; + + /// Get the block’s timestamp. + pub fn timestamp() -> u64; } diff --git a/zink/src/primitives/mod.rs b/zink/src/primitives/mod.rs index f703ad767..1076d5b4c 100644 --- a/zink/src/primitives/mod.rs +++ b/zink/src/primitives/mod.rs @@ -3,6 +3,7 @@ mod address; pub mod bytes; pub mod numeric; +pub mod properties; mod u256; pub use {address::Address, bytes::*, u256::U256}; diff --git a/zink/src/primitives/properties.rs b/zink/src/primitives/properties.rs new file mode 100644 index 000000000..19d790c01 --- /dev/null +++ b/zink/src/primitives/properties.rs @@ -0,0 +1,52 @@ +use super::{Address, Bytes32}; +use crate::ffi; + +/// Get the current block number. +pub fn number() -> u64 { + unsafe { ffi::evm::number() } +} + +/// Get the hash of one of the 256 most recent complete blocks. +pub fn blockhash(block_number: u64) -> Bytes32 { + unsafe { ffi::evm::blockhash(block_number) } +} + +/// Get versioned hashes. +pub fn blobhash(index: u64) -> Bytes32 { + unsafe { ffi::evm::blobhash(index) } +} + +/// Get the current block’s base fee. +pub fn basefee() -> u64 { + unsafe { ffi::evm::basefee() } +} + +/// Get the current block’s blob base fee. +pub fn blobbasefee() -> u64 { + unsafe { ffi::evm::blobbasefee() } +} + +/// Get the current chain id. +pub fn chainid() -> u64 { + unsafe { ffi::evm::chainid() } +} + +/// Get the block’s beneficiary address. +pub fn coinbase() -> Address { + unsafe { ffi::evm::coinbase() } +} + +/// Get the previous block’s RANDAO mix. +pub fn prevrandao() -> Bytes32 { + unsafe { ffi::evm::prevrandao() } +} + +/// Get the current block gaslimit. +pub fn gaslimit() -> u64 { + unsafe { ffi::evm::gaslimit() } +} + +/// Get the block’s timestamp. +pub fn timestamp() -> u64 { + unsafe { ffi::evm::timestamp() } +}