diff --git a/src/kernel_evm/ethereum/src/basic.rs b/src/kernel_evm/ethereum/src/basic.rs deleted file mode 100644 index e60465228d7a1c338f97f252b028c2a589b38a63..0000000000000000000000000000000000000000 --- a/src/kernel_evm/ethereum/src/basic.rs +++ /dev/null @@ -1,447 +0,0 @@ -// SPDX-FileCopyrightText: 2022 TriliTech -// SPDX-FileCopyrightText: 2023 Marigold -// -// SPDX-License-Identifier: MIT - -//! Basic Ethereum types for computation -//! -//! Many of the functions in this module (all the `one` and `zero`) can be made -//! constant, but the underlying library and functions we use are not constant. -//! TODO: -use core::ops::{Add, Div, Mul, Sub}; -use primitive_types::{H256 as PTH256, U256 as PTU256}; -use rlp::{Decodable, DecoderError, Encodable, Rlp}; -use sha3::{Digest, Keccak256}; -use tezos_crypto_rs::hash::BlockHash; -use tezos_smart_rollup_encoding::timestamp::Timestamp; - -/// The size of one 256 bit word. Size in bytes -pub const WORD_SIZE: usize = 32_usize; - -/// Gas price newtype to wrap U256 -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct GasPrice { - /// tezos_encoding doesn't support deriving reader and writer from newtypes so therefore this - /// public field instead. - pub value: U256, -} - -impl GasPrice { - /// Create a new gas price from serilizable u256 - pub fn new(value: U256) -> Self { - Self { value } - } - - /// Create a new gas price from primitive type - pub fn from_u256(value: PTU256) -> Self { - Self { value: U256(value) } - } - - /// Zero - pub fn zero() -> Self { - Self { - value: U256::zero(), - } - } - - /// One - pub fn one() -> Self { - Self { value: U256::one() } - } -} - -impl Decodable for GasPrice { - fn decode(decoder: &Rlp<'_>) -> Result { - Ok(Self { - value: U256::decode(decoder)?, - }) - } -} -impl Encodable for GasPrice { - fn rlp_append(&self, s: &mut rlp::RlpStream) { - s.append(&self.value); - } -} - -/// Gas limit newtype to wrap U256 -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct GasLimit { - /// tezos_encoding doesn't support deriving reader and writer from newtypes so therefore this - /// public field instead. - pub value: U256, -} - -impl GasLimit { - /// Translate to unsigned 64 bit (should be adequate for all calls at the moment) - /// Error can only be overflow. - pub fn to_u64(&self) -> Option { - // Unfortunately, the `primitive_types` library doesn't implement u64 -> U256 - // conversion in `const`. - let max_u64: U256 = U256::from(core::u64::MAX); - - if self.value <= max_u64 { - Some(self.value.0.low_u64()) - } else { - None - } - } - - /// Create a new gas limit from serilizable u256 - pub fn new(value: U256) -> Self { - Self { value } - } - - /// Create a new gas limit from primitive type - pub fn from_u256(value: PTU256) -> Self { - Self { value: U256(value) } - } - - /// Zero - pub fn zero() -> Self { - Self { - value: U256::zero(), - } - } - - /// One - pub fn one() -> Self { - Self { value: U256::one() } - } -} - -impl Decodable for GasLimit { - fn decode(decoder: &Rlp<'_>) -> Result { - Ok(Self { - value: U256::decode(decoder)?, - }) - } -} -impl Encodable for GasLimit { - fn rlp_append(&self, s: &mut rlp::RlpStream) { - s.append(&self.value); - } -} - -/// Amount or value in Wei. Newtype wrapper for U256 -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Wei { - /// tezos_encoding doesn't support deriving reader and writer from newtypes so therefore this - /// public field instead. - pub value: U256, -} - -impl Wei { - /// Create a new value in Wei from serlizable type - pub fn new(value: U256) -> Self { - Self { value } - } - - /// Create a new value in Wei from primitive type - pub fn from_u256(value: PTU256) -> Self { - Self { value: U256(value) } - } - - /// Zero - pub fn zero() -> Self { - Self { - value: U256::zero(), - } - } - - /// One - pub fn one() -> Self { - Self { value: U256::one() } - } -} - -impl Decodable for Wei { - fn decode(decoder: &Rlp<'_>) -> Result { - Ok(Self { - value: U256::decode(decoder)?, - }) - } -} -impl Encodable for Wei { - fn rlp_append(&self, s: &mut rlp::RlpStream) { - s.append(&self.value); - } -} - -/// Unsigned 256 bit integers -#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] -pub struct U256(PTU256); - -impl U256 { - /// Value one 0x00 31 times and then a 0x01 - pub fn one() -> U256 { - U256(PTU256::one()) - } - - /// Value zero - pub fn zero() -> U256 { - U256(PTU256::zero()) - } - - /// Create from slice - data in big endian format - pub fn from_slice_be(data: &[u8]) -> Self { - U256(PTU256::from_big_endian(data)) - } - - /// Create from slice - data in little endian format - pub fn from_slice_le(data: &[u8]) -> Self { - U256(PTU256::from_little_endian(data)) - } -} - -impl std::fmt::Display for U256 { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl From for U256 { - fn from(v: PTU256) -> Self { - Self(v) - } -} - -impl From for U256 { - fn from(v: Timestamp) -> Self { - Self(PTU256::from(v.i64())) - } -} - -impl From for U256 { - fn from(v: i32) -> Self { - Self(PTU256::from(v)) - } -} - -impl From for U256 { - fn from(v: u64) -> Self { - Self(PTU256::from(v)) - } -} - -impl From for U256 { - fn from(v: usize) -> Self { - Self(PTU256::from(v)) - } -} - -impl From for U256 { - fn from(v: u8) -> Self { - Self(PTU256::from(v)) - } -} - -impl Add for U256 { - type Output = U256; - - fn add(self, rhs: U256) -> Self::Output { - U256(self.0 + rhs.0) - } -} - -// Scalar in ethereum RLP encoding is big endian: (taken from yellow paper) -// If RLP is used to encode a scalar, defined only as a non-negative integer (in N, or in Nx for any x), it must be encoded -// as the shortest byte array whose big-endian interpretation is the scala -impl Decodable for U256 { - fn decode(decoder: &Rlp<'_>) -> Result { - Ok(U256::from_slice_be(decoder.data()?)) - } -} - -impl Encodable for U256 { - fn rlp_append(&self, s: &mut rlp::RlpStream) { - // fortunately, primitive types are Encodable - s.append_internal(&self.0); - } -} - -impl Mul for U256 { - type Output = U256; - - fn mul(self, rhs: U256) -> Self::Output { - U256(self.0 * rhs.0) - } -} - -impl Sub for U256 { - type Output = U256; - - fn sub(self, rhs: U256) -> Self::Output { - U256(self.0 - rhs.0) - } -} - -impl Div for U256 { - type Output = U256; - - fn div(self, rhs: U256) -> Self::Output { - U256(self.0 / rhs.0) - } -} - -#[allow(clippy::from_over_into)] -impl Into for U256 { - fn into(self) -> PTU256 { - self.0 - } -} - -impl From for u8 { - fn from(val: U256) -> Self { - PTU256::as_u32(&val.0) as u8 - } -} - -impl From for [u8; WORD_SIZE] { - fn from(v: U256) -> [u8; WORD_SIZE] { - let mut bytes = [0_u8; WORD_SIZE]; - v.0.to_big_endian(&mut bytes); - bytes - } -} - -/// 256 bit hash (Keccak) -#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] -pub struct H256(PTH256); - -impl H256 { - /// Value zero - pub fn zero() -> H256 { - Self(PTH256::zero()) - } - - /// Decode a H256 value from an hex string, unsafe - pub fn from_string_unsafe(s: &str) -> Self { - let mut v: [u8; 32] = [0; 32]; - hex::decode_to_slice(s, &mut v).expect("Could not parse to 256 hex value "); - H256::from(v) - } -} - -impl From<&[u8]> for H256 { - fn from(v: &[u8]) -> Self { - H256(PTH256::from_slice(v)) - } -} - -impl From<[u8; WORD_SIZE]> for H256 { - fn from(v: [u8; WORD_SIZE]) -> Self { - H256(PTH256::from(v)) - } -} - -impl From for H256 { - fn from(v: PTH256) -> Self { - Self(v) - } -} - -#[allow(clippy::from_over_into)] -impl Into for H256 { - fn into(self) -> PTH256 { - self.0 - } -} - -/// Rehashes Tezos block hash to Keccak256 (which is Ehtereum one) -impl From for H256 { - fn from(v: BlockHash) -> Self { - Self(PTH256::from_slice(Keccak256::digest(v.0).as_slice())) - } -} -impl From for String { - fn from(e: H256) -> Self { - format!("{:x}", e.0) - } -} - -impl Decodable for H256 { - fn decode(decoder: &Rlp<'_>) -> Result { - let length = decoder.data()?.len(); - if length == 32 { - Ok(H256::from(decoder.data()?)) - } else if length < 32 && length > 0 { - // there were missing 0 that encoding deleted - let missing = 32 - length; - let mut full = [0u8; 32]; - full[missing..].copy_from_slice(decoder.data()?); - Ok(H256::from(full)) - } else if decoder.data()?.is_empty() { - // considering the case empty allows to decode unsigned transactions - Ok(H256::zero()) - } else { - Err(DecoderError::RlpInvalidLength) - } - } -} - -impl Encodable for H256 { - fn rlp_append(&self, s: &mut rlp::RlpStream) { - if &H256::zero() != self { - s.append(&self.0); - } else { - // we could make the distinction between 0 and null - // but we don't, null is encoded as 0 - // which is not such a big deal as H256 is used for hashed values - s.append_empty_data(); - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - /// used in test to decode a string and get the size of the decoded input, - /// before determining the H256 value - fn decode(str: &str) -> (Result, usize) { - let hash = hex::decode(str).unwrap(); - let decoder = Rlp::new(&hash); - let decoded = H256::decode(&decoder); - assert!(decoded.is_ok(), "hash should be decoded ok"); - let length = decoder.data().unwrap().len(); - (decoded, length) - } - - #[test] - fn test_decode_h256_l0() { - // rlp encoding of empty is the byte 80 - let (decoded, length) = decode("80"); - assert_eq!(0, length); - assert_eq!( - H256::zero(), - decoded.unwrap(), - "empty hash should be decoded as 0x0...0" - ); - } - - #[test] - fn test_decode_h256_l32() { - // rlp encoding of hex string of 32 bytes - let (decoded, length) = - decode("a03232323232323232323232323232323232323232323232323232323232323232"); - assert_eq!(32, length); - assert_eq!( - "3232323232323232323232323232323232323232323232323232323232323232", - String::from(decoded.unwrap()), - "32 hash should be decoded as 0x32...32" - ); - } - - #[test] - fn test_decode_h256_l31() { - // rlp encoding of hex string of 31 bytes - let (decoded, length) = - decode("9f31313131313131313131313131313131313131313131313131313131313131"); - assert_eq!(31, length); - assert_eq!( - "0031313131313131313131313131313131313131313131313131313131313131", - String::from(decoded.unwrap()), - "31 hash should be decoded as 0x0031..31" - ); - } -} diff --git a/src/kernel_evm/ethereum/src/lib.rs b/src/kernel_evm/ethereum/src/lib.rs index 1aed8524697ed2232eca70d92214fe03b8ac5f3d..39fb28f179da263625a4cffbdec242691abb0678 100644 --- a/src/kernel_evm/ethereum/src/lib.rs +++ b/src/kernel_evm/ethereum/src/lib.rs @@ -4,7 +4,6 @@ pub mod account; pub mod address; -pub mod basic; pub mod eth_gen; pub mod signatures; pub mod transaction; diff --git a/src/kernel_evm/ethereum/src/signatures.rs b/src/kernel_evm/ethereum/src/signatures.rs index 199a0d8cd223ef1bc1fb4210cce6a505b81d6ab9..0c7647dae96bd65be3a1ffdd362f5eb59ead27bd 100644 --- a/src/kernel_evm/ethereum/src/signatures.rs +++ b/src/kernel_evm/ethereum/src/signatures.rs @@ -10,12 +10,11 @@ //! as addresses and values. use crate::address::EthereumAddress; -use crate::basic::{GasLimit, GasPrice, Wei, H256, U256}; use libsecp256k1::{ curve::Scalar, recover, sign, verify, Message, PublicKey, RecoveryId, SecretKey, Signature, }; -use primitive_types::H256 as PTH256; +use primitive_types::{H256, U256}; use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpIterator, RlpStream}; use sha3::{Digest, Keccak256}; @@ -55,13 +54,13 @@ pub struct EthereumTransactionCommon { /// Wei to be paid per unit of gas for all computation /// costs incurred as a result of the execution of this /// transaction - pub gas_price: GasPrice, + pub gas_price: U256, /// A scalar value equal to the maximum /// amount of gas that should be used in executing /// this transaction. This is paid up-front, before any /// computation is done and may not be increased /// later - pub gas_limit: GasLimit, + pub gas_limit: U256, /// The 160-bit address of the message call’s recipient /// or, for a contract creation transaction pub to: EthereumAddress, @@ -69,7 +68,7 @@ pub struct EthereumTransactionCommon { /// be transferred to the message call’s recipient or, /// in the case of contract creation, as an endowment /// to the newly created account - pub value: Wei, + pub value: U256, /// the transaction data. In principle this can be large pub data: Vec, /// Signature x-axis part of point on elliptic curve. See yellow paper, appendix F @@ -99,18 +98,18 @@ impl EthereumTransactionCommon { /// Extracts the signature from an EthereumTransactionCommon pub fn signature(&self) -> (Signature, RecoveryId) { // copy r to Scalar - let r: PTH256 = self.r.into(); + let r: H256 = self.r; let r1: [u8; 32] = r.into(); let mut r = Scalar([0; 8]); let _ = r.set_b32(&r1); // copy s to Scalar - let s: PTH256 = self.s.into(); + let s: H256 = self.s; let s1: [u8; 32] = s.into(); let mut s = Scalar([0; 8]); let _ = s.set_b32(&s1); // recompute parity from v and chain_id let ri = self.v - (self.chain_id * U256::from(2) + U256::from(35)); - if let Ok(ri) = RecoveryId::parse(ri.into()) { + if let Ok(ri) = RecoveryId::parse(ri.byte(0)) { (Signature { r, s }, ri) } else { panic!( @@ -142,10 +141,7 @@ impl EthereumTransactionCommon { let mes = self.message(); let (sig, ri) = sign(&mes, &sk); let Signature { r, s } = sig; - let (r, s) = ( - H256::from(PTH256::from(r.b32())), - H256::from(PTH256::from(s.b32())), - ); + let (r, s) = (H256::from(r.b32()), H256::from(s.b32())); let parity: u8 = ri.into(); let v = if self.chain_id == U256::zero() { @@ -183,6 +179,17 @@ impl EthereumTransactionCommon { hex::decode(e).or(Err(DecoderError::Custom("Couldn't parse hex value")))?; Self::from_rlp_bytes(&tx) } + + fn append_internal_h256(h256: &H256, s: &mut rlp::RlpStream) { + if &H256::zero() != h256 { + s.append(h256); + } else { + // we could make the distinction between 0 and null + // but we don't, null is encoded as 0 + // which is not such a big deal as H256 is used for hashed values + s.append_empty_data(); + } + } } impl From for EthereumTransactionCommon { @@ -214,19 +221,45 @@ fn decode_field( decoder.as_val().map_err(custom_err) } +fn decode_h256(decoder: &Rlp<'_>) -> Result { + let length = decoder.data()?.len(); + if length == 32 { + Ok(H256::from_slice(decoder.data()?)) + } else if length < 32 && length > 0 { + // there were missing 0 that encoding deleted + let missing = 32 - length; + let mut full = [0u8; 32]; + full[missing..].copy_from_slice(decoder.data()?); + Ok(H256::from(full)) + } else if decoder.data()?.is_empty() { + // considering the case empty allows to decode unsigned transactions + Ok(H256::zero()) + } else { + Err(DecoderError::RlpInvalidLength) + } +} + +fn decode_field_h256( + decoder: &Rlp<'_>, + field_name: &'static str, +) -> Result { + let custom_err = |_: DecoderError| (DecoderError::Custom(field_name)); + decode_h256(decoder).map_err(custom_err) +} + impl Decodable for EthereumTransactionCommon { fn decode(decoder: &Rlp<'_>) -> Result { if decoder.is_list() && decoder.item_count() == Ok(9) { let mut it = decoder.iter(); let nonce: U256 = decode_field(&next(&mut it)?, "nonce")?; - let gas_price: GasPrice = decode_field(&next(&mut it)?, "gas_price")?; - let gas_limit: GasLimit = decode_field(&next(&mut it)?, "gas_limit")?; + let gas_price: U256 = decode_field(&next(&mut it)?, "gas_price")?; + let gas_limit: U256 = decode_field(&next(&mut it)?, "gas_limit")?; let to: EthereumAddress = decode_field(&next(&mut it)?, "to")?; - let value: Wei = decode_field(&next(&mut it)?, "value")?; + let value: U256 = decode_field(&next(&mut it)?, "value")?; let data: Vec = decode_field(&next(&mut it)?, "data")?; let v: U256 = decode_field(&next(&mut it)?, "v")?; - let r: H256 = decode_field(&next(&mut it)?, "r")?; - let s: H256 = decode_field(&next(&mut it)?, "s")?; + let r: H256 = decode_field_h256(&next(&mut it)?, "r")?; + let s: H256 = decode_field_h256(&next(&mut it)?, "s")?; // in a rlp encoded unsigned eip-155 transaction, v is used to store the chainid // in a rlp encoded signed eip-155 transaction, v is {0,1} + CHAIN_ID * 2 + 35 let chain_id: U256 = if v > U256::from(35) { @@ -256,10 +289,10 @@ impl Encodable for EthereumTransactionCommon { fn rlp_append(&self, stream: &mut RlpStream) { stream.begin_list(9); stream.append(&self.nonce); - stream.append_internal(&self.gas_price); - stream.append_internal(&self.gas_limit); + stream.append(&self.gas_price); + stream.append(&self.gas_limit); stream.append_internal(&self.to); - stream.append_internal(&self.value); + stream.append(&self.value); if self.data.is_empty() { // no data == null, not empty vec stream.append_empty_data(); @@ -267,8 +300,8 @@ impl Encodable for EthereumTransactionCommon { stream.append_iter(self.data.iter().cloned()); } stream.append(&self.v); - stream.append_internal(&self.r); - stream.append_internal(&self.s); + Self::append_internal_h256(&self.r, stream); + Self::append_internal_h256(&self.s, stream); assert!(stream.is_finished()); } } @@ -285,6 +318,59 @@ impl Into> for EthereumTransactionCommon { mod test { use super::*; + fn h256_to_string(e: H256) -> String { + format!("{:x}", e) + } + + /// used in test to decode a string and get the size of the decoded input, + /// before determining the H256 value + fn decode(str: &str) -> (Result, usize) { + let hash = hex::decode(str).unwrap(); + let decoder = Rlp::new(&hash); + let decoded = decode_h256(&decoder); + assert!(decoded.is_ok(), "hash should be decoded ok"); + let length = decoder.data().unwrap().len(); + (decoded, length) + } + + #[test] + fn test_decode_h256_l0() { + // rlp encoding of empty is the byte 80 + let (decoded, length) = decode("80"); + assert_eq!(0, length); + assert_eq!( + H256::zero(), + decoded.unwrap(), + "empty hash should be decoded as 0x0...0" + ); + } + + #[test] + fn test_decode_h256_l32() { + // rlp encoding of hex string of 32 bytes + let (decoded, length) = + decode("a03232323232323232323232323232323232323232323232323232323232323232"); + assert_eq!(32, length); + assert_eq!( + "3232323232323232323232323232323232323232323232323232323232323232", + h256_to_string(decoded.unwrap()), + "32 hash should be decoded as 0x32...32" + ); + } + + #[test] + fn test_decode_h256_l31() { + // rlp encoding of hex string of 31 bytes + let (decoded, length) = + decode("9f31313131313131313131313131313131313131313131313131313131313131"); + assert_eq!(31, length); + assert_eq!( + "0031313131313131313131313131313131313131313131313131313131313131", + h256_to_string(decoded.unwrap()), + "31 hash should be decoded as 0x0031..31" + ); + } + #[test] fn test_caller_classic() { let (_sk, address_from_sk) = string_to_sk_and_address( @@ -314,8 +400,8 @@ mod test { // corresponding address 0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f // signed tx : 0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83 let nonce = U256::from(9); - let gas_price = GasPrice::new(U256::from(20000000000u64)); - let gas_limit = GasLimit::new(U256::from(21000)); + let gas_price = U256::from(20000000000u64); + let gas_limit = U256::from(21000); let to = EthereumAddress::from("3535353535353535353535353535353535353535".to_string()); assert_ne!( @@ -323,7 +409,7 @@ mod test { EthereumAddress::from_u64_be(0), "making sure the expected address is correct" ); - let value = Wei::new(U256::from(1000000000000000000u64)); + let value = U256::from(1000000000000000000u64); let data: Vec = vec![]; let chain_id = U256::one(); let v = chain_id; @@ -385,11 +471,11 @@ mod test { // corresponding address 0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f // signed tx : 0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83 let nonce = U256::from(9); - let gas_price = GasPrice::new(U256::from(20000000000u64)); - let gas_limit = GasLimit::new(U256::from(21000)); + let gas_price = U256::from(20000000000u64); + let gas_limit = U256::from(21000); let to = EthereumAddress::from("3535353535353535353535353535353535353535".to_string()); - let value = Wei::new(U256::from(1000000000000000000u64)); + let value = U256::from(1000000000000000000u64); let data: Vec = vec![]; let chain_id = U256::one(); let v = chain_id; @@ -416,6 +502,12 @@ mod test { assert_eq!(tx, encoded.to_vec()); } + pub fn string_to_h256_unsafe(s: &str) -> H256 { + let mut v: [u8; 32] = [0; 32]; + hex::decode_to_slice(s, &mut v).expect("Could not parse to 256 hex value."); + H256::from(v) + } + #[test] fn test_encoding_create() { // transaction "without to field" @@ -423,17 +515,17 @@ mod test { // corresponding address 0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f // signed tx : 0xf8572e8506c50218ba8304312280843b9aca0082ffff26a0e9637495be4c216a833ef390b1f6798917c8a102ab165c5085cced7ca1f2eb3aa057854e7044a8fee7bccb6a2c32c4229dd9cbacad74350789e0ce75bf40b6f713 let nonce = U256::from(46); - let gas_price = GasPrice::new(U256::from(29075052730u64)); - let gas_limit = GasLimit::new(U256::from(274722)); + let gas_price = U256::from(29075052730u64); + let gas_limit = U256::from(274722); let to = EthereumAddress::from("".to_string()); - let value = Wei::new(U256::from(1000000000u64)); + let value = U256::from(1000000000u64); let data: Vec = hex::decode("ffff").unwrap(); let chain_id = U256::one(); let v = U256::from(38); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "e9637495be4c216a833ef390b1f6798917c8a102ab165c5085cced7ca1f2eb3a", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "57854e7044a8fee7bccb6a2c32c4229dd9cbacad74350789e0ce75bf40b6f713", ); let expected_transaction = EthereumTransactionCommon { @@ -465,18 +557,18 @@ mod test { // corresponding address 0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f // signed tx : 0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83 let nonce = U256::from(9); - let gas_price = GasPrice::new(U256::from(20000000000u64)); - let gas_limit = GasLimit::new(U256::from(21000)); + let gas_price = U256::from(20000000000u64); + let gas_limit = U256::from(21000); let to = EthereumAddress::from("3535353535353535353535353535353535353535".to_string()); - let value = Wei::new(U256::from(1000000000000000000u64)); + let value = U256::from(1000000000000000000u64); let data: Vec = vec![]; let chain_id = U256::one(); let v = U256::from(37); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "28EF61340BD939BC2195FE537567866003E1A15D3C71FF63E1590620AA636276", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "67CBE9D8997F761AECB703304B3800CCF555C9F3DC64214B297FB1966A3B6D83", ); let expected_transaction = EthereumTransactionCommon { @@ -504,17 +596,17 @@ mod test { // arbitrary transaction with data //setup let nonce = U256::from(0); - let gas_price = GasPrice::new(U256::from(40000000000u64)); - let gas_limit = GasLimit::new(U256::from(21000)); + let gas_price = U256::from(40000000000u64); + let gas_limit = U256::from(21000); let to = EthereumAddress::from("423163e58aabec5daa3dd1130b759d24bef0f6ea".to_string()); - let value = Wei::new(U256::from(5000000000000000u64)); + let value = U256::from(5000000000000000u64); let data: Vec = hex::decode("deace8f5000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000041bca408a6b4029b42883aeb2c25087cab76cb58000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000002357a49c7d75f600000000000000000000000000000000000000000000000000000000640b5549000000000000000000000000710bda329b2a6224e4b44833de30f38e7f81d5640000000000000000000000000000000000000000000000000000000000000000").unwrap(); let v = U256::from(37); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "25dd6c973368c45ddfc17f5148e3f468a2e3f2c51920cbe9556a64942b0ab2eb", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "31da07ce40c24b0a01f46fb2abc028b5ccd70dbd1cb330725323edc49a2a9558", ); let expected_transaction = EthereumTransactionCommon { @@ -549,8 +641,8 @@ mod test { // corresponding address 0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f // signed tx : 0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83 let nonce = U256::from(9); - let gas_price = GasPrice::new(U256::from(20000000000u64)); - let gas_limit = GasLimit::new(U256::from(21000)); + let gas_price = U256::from(20000000000u64); + let gas_limit = U256::from(21000); let to = EthereumAddress::from("3535353535353535353535353535353535353535".to_string()); assert_ne!( @@ -558,13 +650,13 @@ mod test { EthereumAddress::from_u64_be(0), "making sure the expected address is correct" ); - let value = Wei::new(U256::from(1000000000000000000u64)); + let value = U256::from(1000000000000000000u64); let data: Vec = vec![]; let v = U256::from(37); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "28EF61340BD939BC2195FE537567866003E1A15D3C71FF63E1590620AA636276", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "67CBE9D8997F761AECB703304B3800CCF555C9F3DC64214B297FB1966A3B6D83", ); let expected_transaction = EthereumTransactionCommon { @@ -619,17 +711,17 @@ mod test { //setup let nonce = U256::from(46); - let gas_price = GasPrice::new(U256::from(29075052730u64)); - let gas_limit = GasLimit::new(U256::from(274722)); + let gas_price = U256::from(29075052730u64); + let gas_limit = U256::from(274722); let to = EthereumAddress::from("ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b".to_string()); - let value = Wei::new(U256::from(760460536160301065u64)); // /!\ > 2^53 -1 + let value = U256::from(760460536160301065u64); // /!\ > 2^53 -1 let data: Vec = hex::decode("3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064023c1700000000000000000000000000000000000000000000000000000000000000030b090c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000a8db2d41b89b009000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000002ab0c205a56c1e000000000000000000000000000000000000000000000000000000a8db2d41b89b00900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000009eb6299e4bb6669e42cb295a254c8492f67ae2c6000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000").unwrap(); let v = U256::from(37); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "c78be9ab81c622c08f7098eefc250935365fb794dfd94aec0fea16c32adec45a", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "5721614264d8490c6866f110c1594151bbcc4fac43758adae644db6bc3314d06", ); let expected_transaction = EthereumTransactionCommon { @@ -667,17 +759,17 @@ mod test { //setup let nonce = U256::from(46); - let gas_price = GasPrice::new(U256::from(29075052730u64)); - let gas_limit = GasLimit::new(U256::from(274722)); + let gas_price = U256::from(29075052730u64); + let gas_limit = U256::from(274722); let to = EthereumAddress::from("ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b".to_string()); - let value = Wei::new(U256::from(760460536160301065u64)); // /!\ > 2^53 -1 + let value = U256::from(760460536160301065u64); // /!\ > 2^53 -1 let data: Vec = hex::decode("3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064023c1700000000000000000000000000000000000000000000000000000000000000030b090c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000a8db2d41b89b009000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000002ab0c205a56c1e000000000000000000000000000000000000000000000000000000a8db2d41b89b00900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000009eb6299e4bb6669e42cb295a254c8492f67ae2c6000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000").unwrap(); let v = U256::from(37); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "c78be9ab81c622c08f7098eefc250935365fb794dfd94aec0fea16c32adec45a", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "5721614264d8490c6866f110c1594151bbcc4fac43758adae644db6bc3314d06", ); let expected_transaction = EthereumTransactionCommon { @@ -720,18 +812,18 @@ mod test { let expected_transaction = EthereumTransactionCommon { chain_id: U256::one(), nonce: U256::from(1), - gas_price: GasPrice::new(U256::from(30000000000u64)), - gas_limit: GasLimit::new(U256::from(1048576)), + gas_price: U256::from(30000000000u64), + gas_limit: U256::from(1048576), to: EthereumAddress::from( "4e1b2c985d729ae6e05ef7974013eeb48f394449".to_string(), ), - value: Wei::new(U256::from(1000000000u64)), + value: U256::from(1000000000u64), data: vec![], v: U256::from(38), - r: H256::from_string_unsafe( + r: string_to_h256_unsafe( "bb03310570362eef497a09dd6e4ef42f56374965cfb09cc4e055a22a2eeac7ad", ), - s: H256::from_string_unsafe( + s: string_to_h256_unsafe( "6053c1bd83abb30c109801844709202208736d598649afe2a53f024b61b3383f", ), }; @@ -764,18 +856,18 @@ mod test { let transaction = EthereumTransactionCommon { chain_id: U256::one(), nonce: U256::from(1), - gas_price: GasPrice::new(U256::from(30000000000u64)), - gas_limit: GasLimit::new(U256::from(1048576)), + gas_price: U256::from(30000000000u64), + gas_limit: U256::from(1048576), to: EthereumAddress::from( "4e1b2c985d729ae6e05ef7974013eeb48f394449".to_string(), ), - value: Wei::new(U256::from(1000000000u64)), + value: U256::from(1000000000u64), data: vec![], v: U256::from(38), - r: H256::from_string_unsafe( + r: string_to_h256_unsafe( "bb03310570362eef497a09dd6e4ef42f56374965cfb09cc4e055a22a2eeac7ad", ), - s: H256::from_string_unsafe( + s: string_to_h256_unsafe( "6053c1bd83abb30c109801844709202208736d598649afe2a53f024b61b3383f", ), }; @@ -805,12 +897,12 @@ mod test { let transaction = EthereumTransactionCommon { chain_id: U256::one(), nonce: U256::from(1), - gas_price: GasPrice::new(U256::from(30000000000u64)), - gas_limit: GasLimit::new(U256::from(1048576)), + gas_price: U256::from(30000000000u64), + gas_limit: U256::from(1048576), to: EthereumAddress::from( "4e1b2c985d729ae6e05ef7974013eeb48f394449".to_string(), ), - value: Wei::new(U256::from(1000000000u64)), + value: U256::from(1000000000u64), data: vec![], v: U256::one(), r: H256::zero(), @@ -823,10 +915,10 @@ mod test { ); let v = U256::from(38); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "bb03310570362eef497a09dd6e4ef42f56374965cfb09cc4e055a22a2eeac7ad", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "6053c1bd83abb30c109801844709202208736d598649afe2a53f024b61b3383f", ); @@ -871,18 +963,18 @@ mod test { let transaction = EthereumTransactionCommon { chain_id: U256::one(), nonce: U256::from(9), - gas_price: GasPrice::new(U256::from(20000000000u64)), - gas_limit: GasLimit::new(U256::from(21000)), + gas_price: U256::from(20000000000u64), + gas_limit: U256::from(21000), to: EthereumAddress::from( "3535353535353535353535353535353535353535".to_string(), ), - value: Wei::new(U256::from(1000000000000000000u64)), + value: U256::from(1000000000000000000u64), data: vec![], v: U256::from(37), - r: H256::from_string_unsafe( + r: string_to_h256_unsafe( "28EF61340BD939BC2195FE537567866003E1A15D3C71FF63E1590620AA636276", ), - s: H256::from_string_unsafe( + s: string_to_h256_unsafe( "67CBE9D8997F761AECB703304B3800CCF555C9F3DC64214B297FB1966A3B6D83", ), }; @@ -902,18 +994,18 @@ mod test { let transaction = EthereumTransactionCommon { chain_id: U256::one(), nonce: U256::from(46), - gas_price: GasPrice::new(U256::from(29075052730u64)), - gas_limit: GasLimit::new(U256::from(274722)), + gas_price: U256::from(29075052730u64), + gas_limit: U256::from(274722), to: EthereumAddress::from( "ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b".to_string(), ), - value: Wei::new(U256::from(760460536160301065u64)), + value: U256::from(760460536160301065u64), data, v: U256::from(37), - r: H256::from_string_unsafe( + r: string_to_h256_unsafe( "c78be9ab81c622c08f7098eefc250935365fb794dfd94aec0fea16c32adec45a", ), - s: H256::from_string_unsafe( + s: string_to_h256_unsafe( "5721614264d8490c6866f110c1594151bbcc4fac43758adae644db6bc3314d06", ), }; @@ -933,12 +1025,12 @@ mod test { let transaction = EthereumTransactionCommon { chain_id: U256::one(), nonce: U256::from(46), - gas_price: GasPrice::new(U256::from(29075052730u64)), - gas_limit: GasLimit::new(U256::from(274722)), + gas_price: U256::from(29075052730u64), + gas_limit: U256::from(274722), to: EthereumAddress::from( "ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b".to_string(), ), - value: Wei::new(U256::from(760460536160301065u64)), + value: U256::from(760460536160301065u64), data, v: U256::one(), r: H256::zero(), @@ -967,12 +1059,12 @@ mod test { let transaction = EthereumTransactionCommon { chain_id: U256::one(), nonce: U256::from(46), - gas_price: GasPrice::new(U256::from(29075052730u64)), - gas_limit: GasLimit::new(U256::from(274722)), + gas_price: U256::from(29075052730u64), + gas_limit: U256::from(274722), to: EthereumAddress::from( "ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b".to_string(), ), - value: Wei::new(U256::from(760460536160301065u64)), + value: U256::from(760460536160301065u64), data, v: U256::zero(), r: H256::zero(), @@ -986,10 +1078,10 @@ mod test { ); let v = U256::from(37); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "c78be9ab81c622c08f7098eefc250935365fb794dfd94aec0fea16c32adec45a", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "5721614264d8490c6866f110c1594151bbcc4fac43758adae644db6bc3314d06", ); @@ -1009,22 +1101,22 @@ mod test { let transaction = EthereumTransactionCommon { chain_id: U256::one(), nonce: U256::from(9), - gas_price: GasPrice::new(U256::from(20000000000u64)), - gas_limit: GasLimit::new(U256::from(21000)), + gas_price: U256::from(20000000000u64), + gas_limit: U256::from(21000), to: EthereumAddress::from( "3535353535353535353535353535353535353535".to_string(), ), - value: Wei::new(U256::from(1000000000000000000u64)), + value: U256::from(1000000000000000000u64), data: vec![], v: U256::one(), r: H256::zero(), s: H256::zero(), }; let v = U256::from(37); - let r = H256::from_string_unsafe( + let r = string_to_h256_unsafe( "28EF61340BD939BC2195FE537567866003E1A15D3C71FF63E1590620AA636276", ); - let s = H256::from_string_unsafe( + let s = string_to_h256_unsafe( "67CBE9D8997F761AECB703304B3800CCF555C9F3DC64214B297FB1966A3B6D83", ); diff --git a/src/kernel_evm/evm_execution/src/account_storage.rs b/src/kernel_evm/evm_execution/src/account_storage.rs index 45725eae88955436dbde454f40edec64129f661c..5f55fa638e2959958135c34c1fe08b77f6c01493 100644 --- a/src/kernel_evm/evm_execution/src/account_storage.rs +++ b/src/kernel_evm/evm_execution/src/account_storage.rs @@ -9,10 +9,12 @@ use host::path::{concat, OwnedPath, Path, RefPath}; use host::runtime::{Runtime, RuntimeError, ValueType}; use primitive_types::{H160, H256, U256}; use sha3::{Digest, Keccak256}; -use tezos_ethereum::basic::WORD_SIZE; use tezos_smart_rollup_storage::storage::Storage; use thiserror::Error; +/// The size of one 256 bit word. Size in bytes +pub const WORD_SIZE: usize = 32_usize; + /// All errors that may happen as result of using the Ethereum account /// interface. #[derive(Error, Copy, Eq, PartialEq, Clone, Debug)] diff --git a/src/kernel_evm/evm_execution/src/block.rs b/src/kernel_evm/evm_execution/src/block.rs index 1d2f349df876d5b5f4e88d86fcfc0e066ce26e5e..b0898c3b8d59a37e49a91fb9bf32e3b07ef48d02 100644 --- a/src/kernel_evm/evm_execution/src/block.rs +++ b/src/kernel_evm/evm_execution/src/block.rs @@ -11,14 +11,13 @@ use super::storage::blocks::get_current_number_n_timestamp; use host::runtime::Runtime; use primitive_types::{H160, U256}; -use tezos_ethereum::basic::{GasLimit, GasPrice, Wei}; /// All data for an Ethereum block. /// /// This data does not change for the duration of the block. All balues are /// updated when the block is finalized and may change for the next block. pub struct BlockConstants { /// Price of one unit of gas in Wei - pub gas_price: GasPrice, + pub gas_price: U256, /// The number of the current block pub number: U256, /// Who is the beneficiary of the current block @@ -29,9 +28,9 @@ pub struct BlockConstants { /// the value to an arbitrary value. pub difficulty: U256, /// Gas limit for the current block. - pub gas_limit: GasLimit, + pub gas_limit: U256, /// The base fee per gas for doing a transaction. - pub base_fee_per_gas: Wei, + pub base_fee_per_gas: U256, /// Identifier for the chain. Normally this would identify the chain (Ethereum /// main net, or some other net). We can use it to identify rollup EVM kernel. pub chain_id: U256, @@ -43,13 +42,13 @@ impl BlockConstants { /// To be done in . pub fn first_block() -> Self { Self { - gas_price: GasPrice::one(), + gas_price: U256::one(), number: U256::zero(), coinbase: H160::zero(), timestamp: U256::zero(), difficulty: U256::zero(), - gas_limit: GasLimit::one(), - base_fee_per_gas: Wei::one(), + gas_limit: U256::one(), + base_fee_per_gas: U256::one(), chain_id: U256::zero(), } } diff --git a/src/kernel_evm/evm_execution/src/handler.rs b/src/kernel_evm/evm_execution/src/handler.rs index ab7640ef452e6c9e6f8c67bf2c18d7c038840263..c07ade6d6107475740f17ca8536225537b56daa6 100644 --- a/src/kernel_evm/evm_execution/src/handler.rs +++ b/src/kernel_evm/evm_execution/src/handler.rs @@ -775,7 +775,7 @@ impl<'a, Host: Runtime> Handler for EvmHandler<'a, Host> { } fn gas_price(&self) -> U256 { - self.block.gas_price.value.into() + self.block.gas_price } fn origin(&self) -> H160 { @@ -804,11 +804,11 @@ impl<'a, Host: Runtime> Handler for EvmHandler<'a, Host> { } fn block_gas_limit(&self) -> U256 { - self.block.gas_limit.value.into() + self.block.gas_limit } fn block_base_fee_per_gas(&self) -> U256 { - self.block.base_fee_per_gas.value.into() + self.block.base_fee_per_gas } fn chain_id(&self) -> U256 { diff --git a/src/kernel_evm/evm_execution/src/lib.rs b/src/kernel_evm/evm_execution/src/lib.rs index 02cc86008dc67e1b14192ced825b2529724a005a..1b34a5cd999034e4783c1bd899ef3b15b30e74c7 100644 --- a/src/kernel_evm/evm_execution/src/lib.rs +++ b/src/kernel_evm/evm_execution/src/lib.rs @@ -64,7 +64,7 @@ pub enum EthereumError { /// A contract call transferred too much gas to sub-context or contract /// call itself got too much gas #[error("Gas limit overflow: {0}")] - GasLimitOverflow(tezos_ethereum::basic::U256), + GasLimitOverflow(U256), } impl From for EthereumError { diff --git a/src/kernel_evm/evm_execution/src/storage.rs b/src/kernel_evm/evm_execution/src/storage.rs index 8a2194a492c259878a49d29f64bd53e06dd7678c..b9c97a290c0ea5df323ad6fa2e627b821f46c6e6 100644 --- a/src/kernel_evm/evm_execution/src/storage.rs +++ b/src/kernel_evm/evm_execution/src/storage.rs @@ -183,8 +183,8 @@ pub mod blocks { pub mod tests { use super::test_utils::blocks_iter; use super::*; - use primitive_types::U256 as PTU256; - use tezos_ethereum::basic::{H256, U256}; + use primitive_types::U256; + use sha3::{Digest, Keccak256}; use tezos_smart_rollup_mock::MockHost; #[test] @@ -197,15 +197,16 @@ pub mod blocks { .take(BLOCKS_STORED + DELETE_BLOCKS_N) .enumerate() .for_each(|(i, (hash, ts))| { - let keccak_hash = H256::from(hash).into(); + let keccak_hash = + H256::from_slice(Keccak256::digest(hash.0).as_slice()); if i == DELETE_BLOCKS_N { last_kept_block_hash = Some(keccak_hash) } add_new_block( &mut mock_host, - PTU256::from(i as i32), + U256::from(i as i32), keccak_hash, - U256::from(ts).into(), + U256::from(ts.i64()), ) .unwrap() }); @@ -213,7 +214,7 @@ pub mod blocks { // Make sure that blocks are cleaned up (0..DELETE_BLOCKS_N).for_each(|i| { assert_eq!( - get_block_hash(&mock_host, PTU256::from(i as i32)) + get_block_hash(&mock_host, U256::from(i as i32)) .expect_err("Blocks should be cleaned up"), EvmBlockStorageError::RuntimeError( host::runtime::RuntimeError::PathNotFound @@ -223,7 +224,7 @@ pub mod blocks { // Make sure that last block is kept assert_eq!( - get_block_hash(&mock_host, PTU256::from(DELETE_BLOCKS_N as i32)) + get_block_hash(&mock_host, U256::from(DELETE_BLOCKS_N as i32)) .unwrap_or_else(|_| panic!( "Block with number {} should be still kept", DELETE_BLOCKS_N diff --git a/src/kernel_evm/kernel/src/block.rs b/src/kernel_evm/kernel/src/block.rs index 522464b58debb6ef303ba7a2b98d4c7d963e875c..2113ac3e4d376002014dccd3abd3e7839f1658d2 100644 --- a/src/kernel_evm/kernel/src/block.rs +++ b/src/kernel_evm/kernel/src/block.rs @@ -128,7 +128,7 @@ fn validate_transaction( storage::read_account_balance(host, &sender_path).unwrap_or_else(|_| Wei::zero()); let sender_nonce = storage::read_account_nonce(host, &sender_path).unwrap_or(U256::zero()); - let nonce: U256 = tx.nonce.into(); + let nonce: U256 = tx.nonce; // For now, we consider there's no gas to pay let gas = Wei::zero(); @@ -202,7 +202,7 @@ fn apply_transaction( index: u32, ) -> Result { let tx = &transaction.transaction; - let value: U256 = tx.value.value.into(); + let value: U256 = tx.value; let gas = Wei::zero(); // First pay for the gas