diff --git a/etherlink/kernel_latest/Cargo.lock b/etherlink/kernel_latest/Cargo.lock index a7dfcdec2dd38deaed8f047af3c9ef1398693c85..15ecab84043258c5789a0e5c55a361379e4bdd9c 100644 --- a/etherlink/kernel_latest/Cargo.lock +++ b/etherlink/kernel_latest/Cargo.lock @@ -3470,6 +3470,7 @@ dependencies = [ "tezos-smart-rollup", "tezos_crypto_rs", "tezos_data_encoding", + "thiserror 1.0.69", ] [[package]] diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index 1b4801ca7e8121eb96f3f5d967e0f60949057517..e2968f578c467b706cc956b5957538b66ac679f3 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -303,7 +303,7 @@ fn next_bip_from_blueprints( next_bip_number, chain_header, blueprint, - ); + )?; Ok(BlueprintParsing::Next(Box::new(bip))) } None => Ok(BlueprintParsing::None), @@ -586,6 +586,7 @@ pub fn produce( mod tests { use super::*; use tezos_execution::account_storage::TezlinkAccount; + use tezos_tezlink::enc_wrappers::BlockHash; use tezos_tezlink::operation::Parameter; use crate::block_storage; @@ -640,7 +641,6 @@ mod tests { use tezos_smart_rollup_host::runtime::Runtime as SdkRuntime; use tezos_tezlink::block::TezBlock; - use tezos_tezlink::operation::BlockHash; use tezos_tezlink::operation::ManagerOperation; use tezos_tezlink::operation::Operation; use tezos_tezlink::operation::OperationContent; diff --git a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs index 34d713a1338f67354e3659f1ed64405be7cafdcc..0dfa1ddb35ed89c5c93d1bc44bdd75351a618b4f 100644 --- a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs @@ -152,10 +152,10 @@ impl From for BlockHeader { fn from(block: TezBlock) -> Self { Self { blueprint_header: BlueprintHeader { - number: block.number, + number: block.number.into(), timestamp: block.timestamp, }, - chain_header: ChainHeader::Tez(TezBlockHeader { hash: block.hash }), + chain_header: ChainHeader::Tez(TezBlockHeader { hash: block.hash.0 }), } } } diff --git a/etherlink/kernel_latest/kernel/src/chains.rs b/etherlink/kernel_latest/kernel/src/chains.rs index fa748566306e6bd30b5960ec0458192c10ab8226..4659d2e608b6e10e8b029c9412e7c89f59a607dd 100644 --- a/etherlink/kernel_latest/kernel/src/chains.rs +++ b/etherlink/kernel_latest/kernel/src/chains.rs @@ -37,6 +37,7 @@ use tezos_smart_rollup::{outbox::OutboxQueue, types::Timestamp}; use tezos_smart_rollup_host::path::{Path, RefPath}; use tezos_tezlink::{ block::{AppliedOperation, TezBlock}, + enc_wrappers::BlockNumber, operation::Operation, operation_result::{ OperationBatchWithMetadata, OperationDataAndMetadata, OperationWithMetadata, @@ -93,7 +94,7 @@ impl BlockInProgressTrait for EthBlockInProgress { } pub struct TezBlockInProgress { - number: U256, + number: BlockNumber, timestamp: Timestamp, previous_hash: H256, applied: Vec, @@ -102,7 +103,7 @@ pub struct TezBlockInProgress { impl BlockInProgressTrait for TezBlockInProgress { fn number(&self) -> U256 { - self.number + self.number.into() } } @@ -236,7 +237,7 @@ pub trait ChainConfigTrait: Debug { current_block_number: U256, previous_chain_header: Self::ChainHeader, blueprint: Blueprint, - ) -> Self::BlockInProgress; + ) -> anyhow::Result; fn read_block_in_progress( host: &impl Runtime, @@ -291,15 +292,15 @@ impl ChainConfigTrait for EvmChainConfig { current_block_number: U256, header: Self::ChainHeader, blueprint: Blueprint, - ) -> Self::BlockInProgress { - eth_bip_from_blueprint( + ) -> anyhow::Result { + Ok(eth_bip_from_blueprint( host, self, tick_counter, current_block_number, header, blueprint, - ) + )) } fn transactions_from_bytes( @@ -428,15 +429,16 @@ impl ChainConfigTrait for MichelsonChainConfig { current_block_number: U256, header: Self::ChainHeader, blueprint: Blueprint, - ) -> Self::BlockInProgress { + ) -> anyhow::Result { let TezTransactions(operations) = blueprint.transactions; - TezBlockInProgress { + let current_block_number: BlockNumber = current_block_number.try_into()?; + Ok(TezBlockInProgress { number: current_block_number, timestamp: blueprint.timestamp, previous_hash: header.hash, applied: vec![], operations: VecDeque::from(operations), - } + }) } fn fetch_hashes_from_delayed_inbox( diff --git a/etherlink/kernel_latest/kernel/src/l2block.rs b/etherlink/kernel_latest/kernel/src/l2block.rs index c53f0b706f1152242806d9f4907490c7e5222733..100c4477223a297391a4be8fd4ffdce87469153d 100644 --- a/etherlink/kernel_latest/kernel/src/l2block.rs +++ b/etherlink/kernel_latest/kernel/src/l2block.rs @@ -23,7 +23,7 @@ impl L2Block { pub fn number(&self) -> U256 { match self { Self::Etherlink(block) => block.number, - Self::Tezlink(block) => block.number, + Self::Tezlink(block) => block.number.into(), } } @@ -58,7 +58,7 @@ impl L2Block { pub fn hash(&self) -> H256 { match self { Self::Etherlink(block) => block.hash, - Self::Tezlink(block) => block.hash, + Self::Tezlink(block) => block.hash.0, } } diff --git a/etherlink/kernel_latest/tezos/Cargo.toml b/etherlink/kernel_latest/tezos/Cargo.toml index 1a080fa2c0092d2c40c0b4d87f83ec6cce2586d2..3be4c3f9b90cbe9be4a7f9280e4101f5be0604f7 100644 --- a/etherlink/kernel_latest/tezos/Cargo.toml +++ b/etherlink/kernel_latest/tezos/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" license = "MIT" [dependencies] +thiserror.workspace = true tezos_crypto_rs.workspace = true hex.workspace = true diff --git a/etherlink/kernel_latest/tezos/src/block.rs b/etherlink/kernel_latest/tezos/src/block.rs index 390a2105212957a986ffac12840896b79e02924b..d0e7dd3b852bdae65e6b2d38be8462dcc1091998 100644 --- a/etherlink/kernel_latest/tezos/src/block.rs +++ b/etherlink/kernel_latest/tezos/src/block.rs @@ -2,129 +2,39 @@ // // SPDX-License-Identifier: MIT -use crate::operation::BlockHash; +use crate::enc_wrappers::{BlockHash, BlockNumber, OperationHash}; use crate::operation_result::OperationDataAndMetadata; -use nom::bytes::complete::take; -use nom::combinator::map; use nom::error::ParseError; use nom::Finish; -use primitive_types::{H256, U256}; +use primitive_types::H256; use tezos_crypto_rs::blake2b::digest_256; use tezos_data_encoding::enc as tezos_enc; -use tezos_data_encoding::nom as tezos_nom; use tezos_data_encoding::nom::error::DecodeError; -use tezos_data_encoding::nom::NomError; +use tezos_data_encoding::nom::{self as tezos_nom}; use tezos_enc::{BinError, BinWriter}; -use tezos_nom::{NomReader, NomResult}; +use tezos_nom::NomReader; use tezos_smart_rollup::types::Timestamp; -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, BinWriter, NomReader)] pub struct AppliedOperation { // OperationHash are 32 bytes long - pub hash: H256, + pub hash: OperationHash, pub branch: BlockHash, + #[encoding(dynamic)] pub op_and_receipt: OperationDataAndMetadata, } -impl NomReader<'_> for AppliedOperation { - fn nom_read(input: &'_ [u8]) -> NomResult<'_, Self> { - let (remaining, hash) = - map(take::(32_usize), H256::from_slice)(input)?; - - let (remaining, branch) = BlockHash::nom_read(remaining)?; - let (remaining, op_and_receipt) = - tezos_nom::dynamic(OperationDataAndMetadata::nom_read)(remaining)?; - - Ok(( - remaining, - Self { - hash, - branch, - op_and_receipt, - }, - )) - } -} - -impl BinWriter for AppliedOperation { - fn bin_write(&self, output: &mut Vec) -> Result<(), BinError> { - let Self { - hash, - branch, - op_and_receipt, - } = self; - // Encode all fields of the AppliedOperation - tezos_enc::put_bytes(&hash.to_fixed_bytes(), output); - branch.bin_write(output)?; - tezos_enc::dynamic(OperationDataAndMetadata::bin_write)(op_and_receipt, output)?; - Ok(()) - } -} - // WIP: This structure will evolve to look like Tezos block -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, BinWriter, NomReader)] pub struct TezBlock { - pub hash: H256, - pub number: U256, + pub hash: BlockHash, + pub number: BlockNumber, + pub previous_hash: BlockHash, pub timestamp: Timestamp, - pub previous_hash: H256, + #[encoding(dynamic, list)] pub operations: Vec, } -impl NomReader<'_> for TezBlock { - fn nom_read(input: &'_ [u8]) -> NomResult<'_, Self> { - let (remaining, hash) = - map(take::(32_usize), H256::from_slice)(input)?; - - let (remaining, number) = nom::number::complete::be_u32(remaining)?; - let number = U256::from(number); - - let (remaining, previous_hash) = - map(take::(32_usize), H256::from_slice)(remaining)?; - - // Decode the timestamp - let (remaining, timestamp) = nom::number::complete::be_i64(remaining)?; - let timestamp = Timestamp::from(timestamp); - - let (remaining, operations) = - tezos_nom::dynamic(tezos_nom::list(AppliedOperation::nom_read))(remaining)?; - - Ok(( - remaining, - Self { - hash, - number, - timestamp, - previous_hash, - operations, - }, - )) - } -} - -impl BinWriter for TezBlock { - // Encoded size for parameter were taken from this command: - // `octez-codec describe block_header binary schema` - fn bin_write(&self, output: &mut Vec) -> Result<(), BinError> { - let Self { - hash, - number, - timestamp, - previous_hash, - operations, - } = self; - // Encode all block fields - tezos_enc::put_bytes(&hash.to_fixed_bytes(), output); - tezos_enc::u32(&number.as_u32(), output)?; - tezos_enc::put_bytes(&previous_hash.to_fixed_bytes(), output); - tezos_enc::i64(×tamp.i64(), output)?; - tezos_enc::dynamic(tezos_enc::list(AppliedOperation::bin_write))( - operations, output, - )?; - Ok(()) - } -} - impl TezBlock { pub fn genesis_block_hash() -> H256 { // This H256 comes from this b58 hash 'BLockGenesisGenesisGenesisGenesisGenesis1db77eJNeJ9' @@ -138,24 +48,24 @@ impl TezBlock { } // This function must be used on a TezBlock whose hash field is H256::zero() - fn hash(&self) -> Result { + fn hash(&self) -> Result { let mut encoded_data = vec![]; self.bin_write(&mut encoded_data)?; let hashed_data = digest_256(&encoded_data); - Ok(H256::from_slice(&hashed_data)) + Ok(BlockHash(H256::from_slice(&hashed_data))) } pub fn new( - number: U256, + number: BlockNumber, timestamp: Timestamp, previous_hash: H256, operations: Vec, ) -> Result { let block = Self { - hash: H256::zero(), + hash: BlockHash(H256::zero()), // Placeholder, will be computed number, timestamp, - previous_hash, + previous_hash: BlockHash(previous_hash), operations, }; Ok(Self { @@ -184,12 +94,12 @@ impl TezBlock { #[cfg(test)] mod tests { - use primitive_types::{H256, U256}; + use primitive_types::H256; use tezos_smart_rollup::types::Timestamp; use crate::operation_result::{ OperationBatchWithMetadata, OperationDataAndMetadata, OperationResult, - OperationResultSum, OperationWithMetadata, RevealSuccess, VecEmpty, + OperationResultSum, OperationWithMetadata, RevealSuccess, }; use super::{AppliedOperation, TezBlock}; @@ -204,14 +114,14 @@ mod tests { } fn dummy_applied_operation() -> AppliedOperation { - let hash = H256::random(); + let hash = H256::random().into(); let data = crate::operation::make_dummy_reveal_operation(); let receipt = OperationResultSum::Reveal(OperationResult { balance_updates: vec![], result: crate::operation_result::ContentResult::Applied(RevealSuccess { consumed_gas: 0u64.into(), }), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); AppliedOperation { hash, @@ -229,7 +139,7 @@ mod tests { } fn dummy_tezblock(operations: Vec) -> TezBlock { - let number = U256::one(); + let number = 1u32.into(); let timestamp = Timestamp::from(0); let previous_hash = TezBlock::genesis_block_hash(); TezBlock::new(number, timestamp, previous_hash, operations) diff --git a/etherlink/kernel_latest/tezos/src/enc_wrappers.rs b/etherlink/kernel_latest/tezos/src/enc_wrappers.rs new file mode 100644 index 0000000000000000000000000000000000000000..551cd8165ded2e1a6f3f5b023a7f03d0ab18b7d0 --- /dev/null +++ b/etherlink/kernel_latest/tezos/src/enc_wrappers.rs @@ -0,0 +1,128 @@ +// SPDX-FileCopyrightText: 2025 Nomadic Labs +// +// SPDX-License-Identifier: MIT + +//! Encoding wrappers for Tezos data types used in Tezlink. + +/// Wrapper types over used in Tezlink, implementing +/// `NomReader` and `BinWriter` to enable derivation for more complex encodings in a tezos compatible way. +use nom::{bytes::complete::take, combinator::map}; +use primitive_types::{H256, U256}; +use std::fmt::Display; +use tezos_data_encoding::enc as tezos_enc; +use tezos_data_encoding::{ + enc::{BinResult, BinWriter}, + nom::{NomError, NomReader, NomResult}, +}; +use thiserror::Error; + +#[derive(PartialEq, Debug, NomReader, BinWriter, Clone, Copy)] +pub struct BlockNumber { + pub block_number: u32, +} + +impl Display for BlockNumber { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + u32::fmt(&self.block_number, f) + } +} + +impl From for BlockNumber { + fn from(block_number: u32) -> Self { + Self { block_number } + } +} + +impl From for u32 { + fn from(block_number: BlockNumber) -> Self { + block_number.block_number + } +} + +impl From for U256 { + fn from(block_number: BlockNumber) -> Self { + block_number.block_number.into() + } +} + +#[derive(Error, Debug)] +pub struct BlockNumberOverflowError; + +impl Display for BlockNumberOverflowError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Overflow during conversion of block number from U256 to u32" + ) + } +} + +impl TryFrom for BlockNumber { + type Error = BlockNumberOverflowError; + + fn try_from(number: U256) -> Result { + if number < U256::from(u32::MAX) { + Ok(Self::from(number.as_u32())) + } else { + Err(BlockNumberOverflowError) + } + } +} + +#[derive(PartialEq, Debug)] +pub struct OperationHash(pub H256); + +impl NomReader<'_> for OperationHash { + fn nom_read(bytes: &[u8]) -> NomResult<'_, Self> { + let (remaining, hash) = + map(take::(32_usize), H256::from_slice)(bytes)?; + Ok((remaining, OperationHash(hash))) + } +} + +impl BinWriter for OperationHash { + fn bin_write(&self, data: &mut Vec) -> BinResult { + tezos_enc::put_bytes(&self.0.to_fixed_bytes(), data); + Ok(()) + } +} + +impl From for OperationHash { + fn from(hash: H256) -> Self { + Self(hash) + } +} + +impl From for H256 { + fn from(hash: OperationHash) -> Self { + hash.0 + } +} + +#[derive(PartialEq, Debug)] +pub struct BlockHash(pub H256); +impl NomReader<'_> for BlockHash { + fn nom_read(bytes: &[u8]) -> NomResult<'_, Self> { + let (remaining, hash) = + map(take::(32_usize), H256::from_slice)(bytes)?; + Ok((remaining, BlockHash(hash))) + } +} + +impl BinWriter for BlockHash { + fn bin_write(&self, data: &mut Vec) -> BinResult { + tezos_enc::put_bytes(&self.0.to_fixed_bytes(), data); + Ok(()) + } +} + +impl From for BlockHash { + fn from(hash: H256) -> Self { + Self(hash) + } +} +impl From for H256 { + fn from(hash: BlockHash) -> Self { + hash.0 + } +} diff --git a/etherlink/kernel_latest/tezos/src/lib.rs b/etherlink/kernel_latest/tezos/src/lib.rs index c8c241be54370f0d330531171fb02219e8cceff5..48e1e958967e4b5a748e36c9c0cdf5af3d14b6cc 100644 --- a/etherlink/kernel_latest/tezos/src/lib.rs +++ b/etherlink/kernel_latest/tezos/src/lib.rs @@ -3,5 +3,6 @@ // SPDX-License-Identifier: MIT pub mod block; +pub mod enc_wrappers; pub mod operation; pub mod operation_result; diff --git a/etherlink/kernel_latest/tezos/src/operation.rs b/etherlink/kernel_latest/tezos/src/operation.rs index 6c9fb03e3e949e23d46f406450eb7e65598811f1..861ddd3f87d90ea079409d97266b8011d3e2d2e6 100644 --- a/etherlink/kernel_latest/tezos/src/operation.rs +++ b/etherlink/kernel_latest/tezos/src/operation.rs @@ -3,19 +3,18 @@ // SPDX-License-Identifier: MIT //! Tezos operations: this module defines the fragment of Tezos operations supported by Tezlink and how to serialize them. - -use mir::ast::michelson_address::entrypoint; /// The whole module is inspired of `src/proto_alpha/lib_protocol/operation_repr.ml` to represent the operation -use nom::combinator::map; +use crate::enc_wrappers::{BlockHash, OperationHash}; +use mir::ast::michelson_address::entrypoint; use nom::error::{ErrorKind, ParseError}; -use nom::{bytes::complete::take, Finish}; +use nom::Finish; use primitive_types::H256; use rlp::Decodable; use tezos_crypto_rs::blake2b::digest_256; use tezos_crypto_rs::hash::UnknownSignature; use tezos_data_encoding::types::Narith; use tezos_data_encoding::{ - enc::{BinError, BinResult, BinWriter}, + enc::{BinError, BinWriter}, nom::{error::DecodeError, NomError, NomReader}, }; use tezos_smart_rollup::types::{Contract, PublicKey, PublicKeyHash}; @@ -93,10 +92,10 @@ impl Operation { Ok(()) } - pub fn hash(&self) -> Result { + pub fn hash(&self) -> Result { let serialized_op = self.to_bytes()?; let op_hash = digest_256(&serialized_op); - Ok(H256::from_slice(&op_hash)) + Ok(OperationHash(H256::from_slice(&op_hash))) } } @@ -108,25 +107,6 @@ impl Decodable for Operation { } } -#[derive(PartialEq, Debug)] -pub struct BlockHash(H256); - -impl NomReader<'_> for BlockHash { - fn nom_read(bytes: &[u8]) -> tezos_data_encoding::nom::NomResult { - let (bytes, hash) = - map(take::(32_usize), H256::from_slice)(bytes)?; - Ok((bytes, Self(hash))) - } -} - -impl BinWriter for BlockHash { - fn bin_write(&self, data: &mut Vec) -> BinResult { - let hash: [u8; 32] = self.0.to_fixed_bytes(); - data.extend_from_slice(&hash); - Ok(()) - } -} - /** There is a distance between the binary format of manager operations @@ -226,12 +206,6 @@ impl From for ManagerOperation { } } -impl From for BlockHash { - fn from(hash: H256) -> Self { - Self(hash) - } -} - #[cfg(test)] fn make_dummy_operation( operation: OperationContent, diff --git a/etherlink/kernel_latest/tezos/src/operation_result.rs b/etherlink/kernel_latest/tezos/src/operation_result.rs index bb2c0bedadd94a5e307bc1178a3f1f0f5e4bf4dd..f20d766ed38883feefe110f60be1751c1bd4e0ac 100644 --- a/etherlink/kernel_latest/tezos/src/operation_result.rs +++ b/etherlink/kernel_latest/tezos/src/operation_result.rs @@ -6,12 +6,9 @@ /// The whole module is inspired of `src/proto_alpha/lib_protocol/apply_result.ml` to represent the result of an operation /// In Tezlink, operation is equivalent to manager operation because there is no other type of operation that interests us. -use nom::branch::alt; -use nom::bytes::complete::tag; -use nom::sequence::preceded; use std::fmt::Debug; use tezos_crypto_rs::hash::UnknownSignature; -use tezos_data_encoding::enc::{self as tezos_enc, u8}; +use tezos_data_encoding::enc as tezos_enc; use tezos_data_encoding::nom as tezos_nom; use tezos_data_encoding::types::Narith; use tezos_enc::BinWriter; @@ -35,60 +32,17 @@ pub enum RevealError { InconsistentPublicKey(PublicKeyHash), } -#[derive(Debug, PartialEq, Eq)] -pub enum TransferError { - BalanceTooLow { - contract: Contract, - balance: Narith, - amount: Narith, - }, - UnspendableContract(Contract), -} - -impl BinWriter for TransferError { - fn bin_write(&self, output: &mut Vec) -> tezos_enc::BinResult { - match self { - Self::BalanceTooLow { - contract, - balance, - amount, - } => { - u8(&0_u8, output)?; - contract.bin_write(output)?; - balance.bin_write(output)?; - amount.bin_write(output)?; - Ok(()) - } - Self::UnspendableContract(contract) => { - u8(&1_u8, output)?; - contract.bin_write(output)?; - Ok(()) - } - } - } +#[derive(Debug, PartialEq, Eq, BinWriter, NomReader)] +pub struct BalanceTooLow { + pub contract: Contract, + pub balance: Narith, + pub amount: Narith, } -impl NomReader<'_> for TransferError { - fn nom_read(input: &'_ [u8]) -> tezos_nom::NomResult<'_, Self> { - let balance_too_low_parser = preceded(tag(0_u8.to_be_bytes()), |input| { - let (input, contract) = Contract::nom_read(input)?; - let (input, balance) = Narith::nom_read(input)?; - let (input, amount) = Narith::nom_read(input)?; - Ok(( - input, - Self::BalanceTooLow { - contract, - balance, - amount, - }, - )) - }); - let unspendable_contract_parser = preceded(tag(1_u8.to_be_bytes()), |input| { - let (input, contract) = Contract::nom_read(input)?; - Ok((input, Self::UnspendableContract(contract))) - }); - alt((balance_too_low_parser, unspendable_contract_parser))(input) - } +#[derive(Debug, PartialEq, Eq, BinWriter, NomReader)] +pub enum TransferError { + BalanceTooLow(BalanceTooLow), + UnspendableContract(Contract), } #[derive(Debug, PartialEq, Eq, NomReader, BinWriter)] @@ -186,38 +140,23 @@ impl NomReader<'_> for Empty { } } -// PlaceHolder Type for temporary unused fields that encode as vectors -#[derive(PartialEq, Debug)] -pub struct VecEmpty; - -impl BinWriter for VecEmpty { - fn bin_write(&self, output: &mut Vec) -> tezos_enc::BinResult { - tezos_enc::u32(&0, output) - } -} -impl NomReader<'_> for VecEmpty { - fn nom_read(input: &'_ [u8]) -> tezos_nom::NomResult<'_, Self> { - // We expect an empty vector, so we just consume the size of the vector - let (input, _) = tezos_nom::size(input)?; - Ok((input, Self)) - } -} - #[derive(PartialEq, Debug, BinWriter, NomReader)] pub struct TransferSuccess { pub storage: Option>, #[encoding(dynamic, list)] pub balance_updates: Vec, // TODO: Placeholder for ticket receipt issue : #8018 - pub ticket_receipt: VecEmpty, + #[encoding(dynamic, bytes)] + pub ticket_receipt: Vec, // TODO: Placeholder for originated contracts issue : #8018 - pub originated_contracts: VecEmpty, + #[encoding(dynamic, bytes)] + pub originated_contracts: Vec, pub consumed_gas: Narith, pub storage_size: Narith, pub paid_storage_size_diff: Narith, pub allocated_destination_contract: bool, // TODO: Placeholder for lazy storage diff issue : #8018 - pub lazy_storage_diff: Option, + pub lazy_storage_diff: Option<()>, } // Inspired from `operation_result` in `src/proto_alpha/lib_protocol/apply_operation_result.ml` @@ -259,7 +198,8 @@ pub struct OperationResult { pub balance_updates: Vec, pub result: ContentResult, //TODO Placeholder for internal operations : #8018 - pub internal_operation_results: VecEmpty, + #[encoding(dynamic, bytes)] + pub internal_operation_results: Vec, } #[derive(PartialEq, Debug)] pub enum OperationResultSum { @@ -274,12 +214,12 @@ pub fn produce_operation_result( Ok(success) => OperationResult { balance_updates: vec![], result: ContentResult::Applied(success), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }, Err(operation_error) => OperationResult { balance_updates: vec![], result: ContentResult::Failed(vec![operation_error]), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }, } } @@ -349,10 +289,10 @@ mod tests { TransferSuccess { storage: None, lazy_storage_diff: None, balance_updates: vec![ BalanceUpdate { balance: Balance::Account(Contract::Implicit(PublicKeyHash::from_b58check("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx").unwrap())), changes: -42000000,update_origin : UpdateOrigin::BlockApplication }, BalanceUpdate { balance: Balance::Account(Contract::Implicit(PublicKeyHash::from_b58check("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN").unwrap())), changes: 42000000,update_origin : UpdateOrigin::BlockApplication} - ], ticket_receipt: VecEmpty, originated_contracts: VecEmpty, consumed_gas: 2169000.into(), storage_size: 0.into(), paid_storage_size_diff: 0.into(), allocated_destination_contract: false } + ], ticket_receipt: vec![], originated_contracts: vec![], consumed_gas: 2169000.into(), storage_size: 0.into(), paid_storage_size_diff: 0.into(), allocated_destination_contract: false } )) - , internal_operation_results: VecEmpty }) + , internal_operation_results: vec![] }) }], signature: UnknownSignature::from_base58_check( "sigPc9gwEse2o5nsicnNeWLjLgoMbEGumXw7PErAkMMa1asXVKRq43RPd7TnUKYwuHmejxEu15XTyV1iKGiaa8akFHK7CCEF" diff --git a/etherlink/kernel_latest/tezos_execution/src/lib.rs b/etherlink/kernel_latest/tezos_execution/src/lib.rs index 0df0d7511f260603376101c373cbad94c8eab965..609e7555642417d7006c0a1f95c0f0cec851e6b5 100644 --- a/etherlink/kernel_latest/tezos_execution/src/lib.rs +++ b/etherlink/kernel_latest/tezos_execution/src/lib.rs @@ -16,7 +16,7 @@ use tezos_data_encoding::types::Narith; use tezos_evm_logging::{log, Level::*}; use tezos_evm_runtime::runtime::Runtime; use tezos_smart_rollup::types::{Contract, PublicKey, PublicKeyHash}; -use tezos_tezlink::operation_result::{TransferTarget, UpdateOrigin, VecEmpty}; +use tezos_tezlink::operation_result::{BalanceTooLow, TransferTarget, UpdateOrigin}; use tezos_tezlink::{ operation::{ ManagerOperation, OperationContent, Parameter, RevealContent, TransferContent, @@ -186,11 +186,11 @@ pub fn transfer( let new_source_balance = match current_src_balance.checked_sub(&amount.0) { None => { log!(host, Debug, "Balance is too low"); - let error = TransferError::BalanceTooLow { + let error = TransferError::BalanceTooLow(BalanceTooLow { contract: src_contract.clone(), balance: current_src_balance.into(), amount: amount.clone(), - }; + }); return Ok(Err(error.into())); } Some(new_source_balance) => new_source_balance, @@ -217,8 +217,8 @@ pub fn transfer( storage: None, lazy_storage_diff: None, balance_updates: vec![src_update, dest_update], - ticket_receipt: VecEmpty, - originated_contracts: VecEmpty, + ticket_receipt: vec![], + originated_contracts: vec![], consumed_gas: 0_u64.into(), storage_size: 0_u64.into(), paid_storage_size_diff: 0_u64.into(), @@ -244,8 +244,8 @@ pub fn transfer( storage: Some(new_storage), lazy_storage_diff: None, balance_updates: vec![src_update, dest_update], - ticket_receipt: VecEmpty, - originated_contracts: VecEmpty, + ticket_receipt: vec![], + originated_contracts: vec![], consumed_gas: 0_u64.into(), storage_size: 0_u64.into(), paid_storage_size_diff: 0_u64.into(), @@ -409,14 +409,15 @@ mod tests { use tezos_smart_rollup::types::{Contract, PublicKey, PublicKeyHash}; use tezos_tezlink::{ block::TezBlock, + enc_wrappers::BlockHash, operation::{ - BlockHash, ManagerOperation, Operation, OperationContent, Parameter, - RevealContent, TransferContent, + ManagerOperation, Operation, OperationContent, Parameter, RevealContent, + TransferContent, }, operation_result::{ - Balance, BalanceUpdate, ContentResult, OperationResult, OperationResultSum, - RevealError, RevealSuccess, TransferError, TransferSuccess, TransferTarget, - UpdateOrigin, VecEmpty, + Balance, BalanceTooLow, BalanceUpdate, ContentResult, OperationResult, + OperationResultSum, RevealError, RevealSuccess, TransferError, + TransferSuccess, TransferTarget, UpdateOrigin, }, }; @@ -552,7 +553,7 @@ mod tests { result: ContentResult::Failed(vec![OperationError::Validation( ValidityError::EmptyImplicitContract, )]), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); assert_eq!(receipt, expected_receipt); @@ -588,7 +589,7 @@ mod tests { result: ContentResult::Failed(vec![OperationError::Validation( ValidityError::CantPayFees(50_u64.into()), )]), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); assert_eq!(receipt, expected_receipt); @@ -624,7 +625,7 @@ mod tests { result: ContentResult::Failed(vec![OperationError::Validation( ValidityError::InvalidCounter(0_u64.into()), )]), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); assert_eq!(receipt, expected_receipt); } @@ -666,7 +667,7 @@ mod tests { result: ContentResult::Failed(vec![OperationError::Apply( RevealError::PreviouslyRevealedKey(pk).into(), )]), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); assert_eq!(receipt, expected_receipt); } @@ -710,7 +711,7 @@ mod tests { result: ContentResult::Failed(vec![OperationError::Apply( RevealError::InconsistentHash(inconsistent_pkh).into(), )]), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); assert_eq!(receipt, expected_receipt); @@ -747,7 +748,7 @@ mod tests { result: ContentResult::Failed(vec![OperationError::Apply( RevealError::InconsistentPublicKey(src).into(), )]), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); assert_eq!(receipt, expected_receipt); @@ -788,7 +789,7 @@ mod tests { result: ContentResult::Applied(RevealSuccess { consumed_gas: 0_u64.into(), }), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); assert_eq!(receipt, expected_receipt); @@ -836,14 +837,14 @@ mod tests { let expected_receipt = OperationResultSum::Transfer(OperationResult { balance_updates: vec![], result: ContentResult::Failed(vec![OperationError::Apply( - TransferError::BalanceTooLow { + TransferError::BalanceTooLow(BalanceTooLow { contract: Contract::from_b58check(BOOTSTRAP_1).unwrap(), balance: 50_u64.into(), amount: 100_u64.into(), - } + }) .into(), )]), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); // Verify that source and destination balances are unchanged @@ -907,14 +908,14 @@ mod tests { update_origin: UpdateOrigin::BlockApplication, }, ], - ticket_receipt: VecEmpty, - originated_contracts: VecEmpty, + ticket_receipt: vec![], + originated_contracts: vec![], consumed_gas: 0_u64.into(), storage_size: 0_u64.into(), paid_storage_size_diff: 0_u64.into(), allocated_destination_contract: true, })), - internal_operation_results: VecEmpty, + internal_operation_results: vec![], }); // Verify that source and destination balances changed