diff --git a/Cargo.toml b/Cargo.toml index 797eacfc..8dd8ad8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,10 @@ members = [ "cartesi-rollups/node/epoch-manager", "cartesi-rollups/node/machine-runner", "cartesi-rollups/node/state-manager", + + # machine bindings + "machine/rust-bindings/cartesi-machine", + "machine/rust-bindings/cartesi-machine-sys", ] [workspace.package] diff --git a/cartesi-rollups/node/blockchain-reader/src/lib.rs b/cartesi-rollups/node/blockchain-reader/src/lib.rs index 7cef17f5..f4af7c8c 100644 --- a/cartesi-rollups/node/blockchain-reader/src/lib.rs +++ b/cartesi-rollups/node/blockchain-reader/src/lib.rs @@ -443,26 +443,17 @@ impl PartitionProvider { mod blockchain_reader_tests { use crate::*; use alloy::{ + hex::FromHex, network::EthereumWallet, node_bindings::{Anvil, AnvilInstance}, primitives::Address, providers::ProviderBuilder, - signers::local::PrivateKeySigner, - signers::Signer, + signers::{local::PrivateKeySigner, Signer}, sol_types::{SolCall, SolValue}, transports::http::{Client, Http}, }; use cartesi_dave_contracts::daveconsensus::DaveConsensus::{self, EpochSealed}; use cartesi_dave_merkle::Digest; - use cartesi_prt_contracts::{ - bottomtournamentfactory::BottomTournamentFactory, - middletournamentfactory::MiddleTournamentFactory, - multileveltournamentfactory::MultiLevelTournamentFactory::{ - self, CommitmentStructure, DisputeParameters, MultiLevelTournamentFactoryInstance, - TimeConstants, - }, - toptournamentfactory::TopTournamentFactory, - }; use cartesi_prt_core::arena::SenderFiller; use cartesi_rollups_contracts::{ inputbox::InputBox::{self, InputAdded}, @@ -479,13 +470,24 @@ mod blockchain_reader_tests { type Result = std::result::Result>; const APP_ADDRESS: Address = Address::ZERO; - const INITIAL_STATE: Digest = Digest::ZERO; + // $ xxd -p -c32 test/programs/echo/machine-image/hash + const INITIAL_STATE: &str = + "0x84c8181abd120e0281f5032d22422b890f79880ae90d9a1416be1afccb8182a0"; const INPUT_PAYLOAD: &str = "Hello!"; const INPUT_PAYLOAD2: &str = "Hello Two!"; - fn spawn_anvil_and_provider() -> (AnvilInstance, Arc) { - let args = vec!["--slots-in-an-epoch", "1"]; - let anvil = Anvil::default().block_time(1).args(args).spawn(); + fn spawn_anvil_and_provider() -> (AnvilInstance, SenderFiller, Address, Address) { + let anvil = Anvil::default() + .block_time(1) + .args([ + "--disable-code-size-limit", + "--preserve-historical-states", + "--slots-in-an-epoch", + "1", + "--load-state", + "../../../test/programs/echo/anvil_state.json", + ]) + .spawn(); let mut signer: PrivateKeySigner = anvil.keys()[0].clone().into(); @@ -497,7 +499,12 @@ mod blockchain_reader_tests { .wallet(wallet) .on_http(anvil.endpoint_url()); - (anvil, Arc::new(provider)) + ( + anvil, + provider, + Address::from_hex("0x5fbdb2315678afecb367f032d93f642f64180aa3").unwrap(), + Address::from_hex("0x0165878a594ca255338adfa4d48449f69242eb8f").unwrap(), + ) } fn create_partition_rovider(url: &str) -> Result { @@ -513,70 +520,8 @@ mod blockchain_reader_tests { EventReader::::new() } - async fn deploy_inputbox<'a>( - provider: &'a Arc, - ) -> Result, &'a Arc>>> { - let inputbox = InputBox::deploy(provider).await?; - Ok(Arc::new(inputbox)) - } - - async fn deploy_daveconsensus<'a>( - provider: &'a Arc, - inputbox: &Address, - tournament_factory: &Address, - ) -> Result, &'a Arc>>> - { - let daveconsensus = DaveConsensus::deploy( - provider, - *inputbox, - APP_ADDRESS, - *tournament_factory, - INITIAL_STATE.into(), - ) - .await?; - Ok(Arc::new(daveconsensus)) - } - - async fn deploy_tournamentfactories<'a>( - provider: &'a Arc, - ) -> Result, &'a Arc>>> { - let dispute_parameters = DisputeParameters { - timeConstants: TimeConstants { - matchEffort: 60 * 2, - maxAllowance: 60 * (60 + 5 + 2), - }, - commitmentStructures: vec![ - CommitmentStructure { - log2step: 44, - height: 48, - }, - CommitmentStructure { - log2step: 28, - height: 16, - }, - CommitmentStructure { - log2step: 0, - height: 28, - }, - ], - }; - - let top_tournamentfactory = TopTournamentFactory::deploy(provider).await?; - let mid_tournamentfactory = MiddleTournamentFactory::deploy(provider).await?; - let bottom_tournamentfactory = BottomTournamentFactory::deploy(provider).await?; - let multi_tournamentfactory = MultiLevelTournamentFactory::deploy( - provider, - *top_tournamentfactory.address(), - *mid_tournamentfactory.address(), - *bottom_tournamentfactory.address(), - dispute_parameters, - ) - .await?; - Ok(Arc::new(multi_tournamentfactory)) - } - - async fn add_input<'a>( - inputbox: &'a Arc, &'a Arc>>, + async fn add_input( + inputbox: &InputBox::InputBoxInstance, impl Provider>>, input_payload: &'static str, count: usize, ) -> Result<()> { @@ -669,40 +614,40 @@ mod blockchain_reader_tests { #[tokio::test] async fn test_input_reader() -> Result<()> { - let (anvil, provider) = spawn_anvil_and_provider(); + let (anvil, provider, input_box_address, _) = spawn_anvil_and_provider(); + let inputbox = InputBox::new(input_box_address, &provider); - let inputbox = deploy_inputbox(&provider).await?; - - let mut input_count = 2; - add_input(&inputbox, &INPUT_PAYLOAD, input_count).await?; + let input_count_1 = 2; + // Inputbox is deployed with 1 input already + add_input(&inputbox, INPUT_PAYLOAD, input_count_1).await?; let input_reader = create_input_reader(); let mut read_inputs = read_inputs_until_count( &anvil.endpoint(), inputbox.address(), &input_reader, - input_count, + 1 + input_count_1, ) .await?; - assert_eq!(read_inputs.len(), input_count); + assert_eq!(read_inputs.len(), 1 + input_count_1); let received_payload = - EvmAdvanceCall::abi_decode(read_inputs[input_count - 1].input.as_ref(), true)?; + EvmAdvanceCall::abi_decode(read_inputs.last().unwrap().input.as_ref(), true)?; assert_eq!(received_payload.payload.as_ref(), INPUT_PAYLOAD.as_bytes()); - input_count = 3; - add_input(&inputbox, &INPUT_PAYLOAD2, input_count).await?; + let input_count_2 = 3; + add_input(&inputbox, INPUT_PAYLOAD2, input_count_2).await?; read_inputs = read_inputs_until_count( &anvil.endpoint(), inputbox.address(), &input_reader, - input_count, + 1 + input_count_1 + input_count_2, ) .await?; - assert_eq!(read_inputs.len(), input_count); + assert_eq!(read_inputs.len(), 1 + input_count_1 + input_count_2); let received_payload = - EvmAdvanceCall::abi_decode(read_inputs[input_count - 1].input.as_ref(), true)?; + EvmAdvanceCall::abi_decode(read_inputs.last().unwrap().input.as_ref(), true)?; assert_eq!(received_payload.payload.as_ref(), INPUT_PAYLOAD2.as_bytes()); drop(anvil); @@ -711,16 +656,8 @@ mod blockchain_reader_tests { #[tokio::test] async fn test_epoch_reader() -> Result<()> { - let (anvil, provider) = spawn_anvil_and_provider(); - - let inputbox = deploy_inputbox(&provider).await?; - let multi_tournamentfactory = deploy_tournamentfactories(&provider).await?; - let daveconsensus = deploy_daveconsensus( - &provider, - inputbox.address(), - multi_tournamentfactory.address(), - ) - .await?; + let (anvil, provider, _, consensus_address) = spawn_anvil_and_provider(); + let daveconsensus = DaveConsensus::new(consensus_address, &provider); let epoch_reader = create_epoch_reader(); let read_epochs = @@ -729,7 +666,7 @@ mod blockchain_reader_tests { assert_eq!(read_epochs.len(), 1); assert_eq!( &read_epochs[0].initialMachineStateHash.abi_encode(), - INITIAL_STATE.slice() + Digest::from_digest_hex(INITIAL_STATE).unwrap().slice() ); drop(anvil); @@ -738,24 +675,18 @@ mod blockchain_reader_tests { #[tokio::test] async fn test_blockchain_reader() -> Result<()> { - let (anvil, provider) = spawn_anvil_and_provider(); + let (anvil, provider, input_box_address, consensus_address) = spawn_anvil_and_provider(); - let inputbox = deploy_inputbox(&provider).await?; + let inputbox = InputBox::new(input_box_address, &provider); let state_manager = Arc::new(PersistentStateAccess::new( Connection::open_in_memory().unwrap(), )?); // add inputs to epoch 0 let mut input_count = 2; - add_input(&inputbox, &INPUT_PAYLOAD, input_count).await?; + add_input(&inputbox, INPUT_PAYLOAD, input_count).await?; - let multi_tournamentfactory = deploy_tournamentfactories(&provider).await?; - let daveconsensus = deploy_daveconsensus( - &provider, - inputbox.address(), - multi_tournamentfactory.address(), - ) - .await?; + let daveconsensus = DaveConsensus::new(consensus_address, &provider); let mut blockchain_reader = BlockchainReader::new( state_manager.clone(), AddressBook { @@ -767,7 +698,7 @@ mod blockchain_reader_tests { 1, )?; - let _ = spawn(async move { + let r = spawn(async move { blockchain_reader.start().await.unwrap(); }); @@ -775,15 +706,16 @@ mod blockchain_reader_tests { // add inputs to epoch 1 input_count = 3; - add_input(&inputbox, &INPUT_PAYLOAD, input_count).await?; + add_input(&inputbox, INPUT_PAYLOAD, input_count).await?; read_inputs_from_db_until_count(&state_manager, 1, input_count).await?; // add more inputs to epoch 1 let more_input_count = 3; - add_input(&inputbox, &INPUT_PAYLOAD, more_input_count).await?; + add_input(&inputbox, INPUT_PAYLOAD, more_input_count).await?; read_inputs_from_db_until_count(&state_manager, 1, input_count + more_input_count).await?; drop(anvil); + drop(r); Ok(()) } } diff --git a/cartesi-rollups/node/dave-rollups/src/lib.rs b/cartesi-rollups/node/dave-rollups/src/lib.rs index 6e056fca..9b92bbdc 100644 --- a/cartesi-rollups/node/dave-rollups/src/lib.rs +++ b/cartesi-rollups/node/dave-rollups/src/lib.rs @@ -3,9 +3,9 @@ use cartesi_prt_core::arena::{BlockchainConfig, EthArenaSender, SenderFiller}; use clap::Parser; use log::error; use rollups_blockchain_reader::{AddressBook, BlockchainReader}; -use rollups_prt_runner::ComputeRunner; use rollups_epoch_manager::EpochManager; use rollups_machine_runner::MachineRunner; +use rollups_prt_runner::ComputeRunner; use rollups_state_manager::persistent_state_access::PersistentStateAccess; use std::path::PathBuf; use std::sync::Arc; diff --git a/common-rs/merkle/src/digest/keccak.rs b/common-rs/merkle/src/digest/keccak.rs index 7a4757ca..65bc856e 100644 --- a/common-rs/merkle/src/digest/keccak.rs +++ b/common-rs/merkle/src/digest/keccak.rs @@ -22,4 +22,3 @@ impl Digest { Digest::from(digest) } } - diff --git a/machine/rust-bindings/cartesi-machine/src/proof.rs b/machine/rust-bindings/cartesi-machine/src/proof.rs index 17dab0ae..38e93254 100644 --- a/machine/rust-bindings/cartesi-machine/src/proof.rs +++ b/machine/rust-bindings/cartesi-machine/src/proof.rs @@ -44,8 +44,9 @@ impl MerkleTreeProof { /// Sibling hashes towards root pub fn sibling_hashes(&self) -> Vec { let sibling_hashes = unsafe { (*self.0).sibling_hashes }; - let sibling_hashes = unsafe { std::slice::from_raw_parts(sibling_hashes.entry, sibling_hashes.count) }; + let sibling_hashes = + unsafe { std::slice::from_raw_parts(sibling_hashes.entry, sibling_hashes.count) }; sibling_hashes.iter().map(|hash| Hash::new(*hash)).collect() } -} \ No newline at end of file +} diff --git a/prt/tests/common/blockchain/node.lua b/prt/tests/common/blockchain/node.lua index 80ca463e..c891cee5 100644 --- a/prt/tests/common/blockchain/node.lua +++ b/prt/tests/common/blockchain/node.lua @@ -9,13 +9,13 @@ local function start_blockchain(load_state) local cmd if load_state then cmd = string.format( - [[sh -c "echo $$ ; exec anvil --load-state %s --block-time 1 --slots-in-an-epoch 1 -a %d > anvil.log 2>&1"]], + [[sh -c "echo $$ ; exec anvil --load-state %s --disable-code-size-limit --preserve-historical-states --block-time 1 --slots-in-an-epoch 1 -a %d > anvil.log 2>&1"]], load_state, default_account_number ) else cmd = string.format( - [[sh -c "echo $$ ; exec anvil --block-time 1 --slots-in-an-epoch 1 -a %d > anvil.log 2>&1"]], + [[sh -c "echo $$ ; exec anvil --disable-code-size-limit --preserve-historical-states --block-time 1 --slots-in-an-epoch 1 -a %d > anvil.log 2>&1"]], default_account_number ) end diff --git a/prt/tests/common/blockchain/utils.lua b/prt/tests/common/blockchain/utils.lua index 20670ac5..8b4024cd 100644 --- a/prt/tests/common/blockchain/utils.lua +++ b/prt/tests/common/blockchain/utils.lua @@ -19,6 +19,7 @@ local function advance_time(blocks, endpoint) end end +-- TODO remove this, since we're dumping/loading an "ready" anvil state. local deploy_cmd = [[sh -c "cd %s && ./deploy_anvil.sh"]] local function deploy_contracts(contracts_path) local reader = io.popen(string.format(deploy_cmd, contracts_path)) diff --git a/test/programs/build_anvil_state.sh b/test/programs/build_anvil_state.sh index 8eb51ac8..2d105e0e 100755 --- a/test/programs/build_anvil_state.sh +++ b/test/programs/build_anvil_state.sh @@ -6,7 +6,7 @@ mkdir -p $program_path # start anvil with dump state rm -f $program_path/anvil_state.json -anvil --disable-code-size-limit \ +anvil --disable-code-size-limit --preserve-historical-states --slots-in-an-epoch 1 \ --dump-state $program_path/anvil_state.json > $program_path/_anvil.log 2>&1 & anvil_pid=$! sleep 5 @@ -28,6 +28,8 @@ jq -r '.transactions[] | select(.transactionType=="CREATE") | select(.contractNa ../../cartesi-rollups/contracts/broadcast/DaveConsensus.s.sol/31337/run-latest.json \ >> $program_path/addresses +cast rpc anvil_mine 2 + # # kill anvil, thus dumping its state, to be loaded later by tests kill -INT "$anvil_pid"