diff --git a/Cargo.lock b/Cargo.lock index e1889df39..bf649258e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1492,48 +1492,27 @@ dependencies = [ [[package]] name = "borsh" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "bytes", - "hashbrown 0.13.2", + "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2 1.0.85", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2 1.0.85", - "quote 1.0.36", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ + "once_cell", + "proc-macro-crate", "proc-macro2 1.0.85", "quote 1.0.36", - "syn 1.0.109", + "syn 2.0.66", + "syn_derive", ] [[package]] @@ -1702,6 +1681,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.38" @@ -1924,6 +1909,7 @@ dependencies = [ "anyhow", "bincode", "bonsai-sdk", + "borsh", "bytemuck", "hex", "once_cell", @@ -2086,7 +2072,7 @@ dependencies = [ "directories", "serde", "thiserror", - "toml 0.8.14", + "toml", ] [[package]] @@ -2592,7 +2578,7 @@ dependencies = [ "sov-value-setter", "tempfile", "tokio", - "toml 0.8.14", + "toml", "tracing", ] @@ -4318,8 +4304,8 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jmt" -version = "0.9.0" -source = "git+https://github.com/penumbra-zone/jmt.git?rev=1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6#1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6" +version = "0.10.0" +source = "git+https://github.com/penumbra-zone/jmt.git?rev=fd1c8ef#fd1c8ef99913663eb801576a9b13a31523861d87" dependencies = [ "anyhow", "borsh", @@ -4450,7 +4436,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d0bb047e79a143b32ea03974a6bf59b62c2a4c5f5d42a381c907a8bbb3f75c0" dependencies = [ "heck 0.4.1", - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2 1.0.85", "quote 1.0.36", "syn 2.0.66", @@ -5389,7 +5375,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2 1.0.85", "quote 1.0.36", "syn 2.0.66", @@ -5514,7 +5500,7 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2 1.0.85", "quote 1.0.36", "syn 1.0.109", @@ -5827,15 +5813,6 @@ dependencies = [ "uint", ] -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml 0.5.11", -] - [[package]] name = "proc-macro-crate" version = "3.1.0" @@ -8640,6 +8617,7 @@ dependencies = [ "borsh", "derive_more", "digest 0.10.7", + "hashbrown 0.14.5", "hex", "jmt", "proptest", @@ -8766,6 +8744,7 @@ version = "0.4.0-rc.3" dependencies = [ "anyhow", "bincode", + "borsh", "bytemuck", "once_cell", "parking_lot 0.12.3", @@ -8943,7 +8922,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.14", + "toml", "tower", "tower-http", "tracing", @@ -9166,6 +9145,18 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -9458,15 +9449,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.8.14" @@ -9814,7 +9796,7 @@ dependencies = [ "serde_derive", "serde_json", "termcolor", - "toml 0.8.14", + "toml", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5b483dcfc..f9f2da63e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ repository = "https://github.com/chainwayxyz/citrea" [workspace.dependencies] # Dependencies maintained by Sovereign -jmt = { git = "https://github.com/penumbra-zone/jmt.git", rev = "1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6" } +jmt = { git = "https://github.com/penumbra-zone/jmt.git", rev = "fd1c8ef" } # External dependencies async-trait = "0.1.71" @@ -73,7 +73,7 @@ anyhow = { version = "1.0.68", default-features = false } arbitrary = { version = "1.3.1", features = ["derive"] } backoff = { version = "0.4.0", features = ["futures", "tokio"] } base64 = "0.13" -borsh = { version = "0.10.3", default-features = false } +borsh = { version = "1.5", default-features = false, features = ["derive"] } # TODO: Consider replacing this serialization format # https://github.com/Sovereign-Labs/sovereign-sdk/issues/283 bincode = "1.3.3" @@ -91,6 +91,7 @@ postgres-types = "0.2.6" rs_merkle = "1.4.2" futures = "0.3" pin-project = { version = "1.1.3" } +hashbrown = { version = "0.14", default-features = false, features = ["ahash"] } hex = { version = "0.4.3", default-features = false, features = ["alloc", "serde"] } log-panics = { version = "2", features = ["with-backtrace"] } once_cell = { version = "1.19.0", default-features = false, features = ["alloc"] } diff --git a/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock b/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock index 785ce103f..d7726da5b 100644 --- a/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock +++ b/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock @@ -727,48 +727,27 @@ dependencies = [ [[package]] name = "borsh" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "bytes", - "hashbrown 0.13.2", + "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ + "once_cell", + "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", + "syn_derive", ] [[package]] @@ -865,6 +844,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.38" @@ -1859,8 +1844,8 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jmt" -version = "0.9.0" -source = "git+https://github.com/penumbra-zone/jmt.git?rev=1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6#1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6" +version = "0.10.0" +source = "git+https://github.com/penumbra-zone/jmt.git?rev=fd1c8ef#fd1c8ef99913663eb801576a9b13a31523861d87" dependencies = [ "anyhow", "borsh", @@ -2151,7 +2136,7 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -2231,15 +2216,6 @@ dependencies = [ "uint", ] -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - [[package]] name = "proc-macro-crate" version = "3.1.0" @@ -3101,6 +3077,7 @@ dependencies = [ "borsh", "derive_more", "digest 0.10.7", + "hashbrown 0.14.5", "hex", "jmt", "schemars", @@ -3148,6 +3125,7 @@ version = "0.4.0-rc.3" dependencies = [ "anyhow", "bincode", + "borsh", "bytemuck", "risc0-zkvm", "risc0-zkvm-platform", @@ -3325,6 +3303,18 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "synstructure" version = "0.13.1" @@ -3433,15 +3423,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml_datetime" version = "0.6.6" diff --git a/bin/citrea/provers/risc0/guest-mock/Cargo.lock b/bin/citrea/provers/risc0/guest-mock/Cargo.lock index 20f3c7897..8d3440a90 100644 --- a/bin/citrea/provers/risc0/guest-mock/Cargo.lock +++ b/bin/citrea/provers/risc0/guest-mock/Cargo.lock @@ -645,48 +645,27 @@ dependencies = [ [[package]] name = "borsh" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "bytes", - "hashbrown 0.13.2", + "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ + "once_cell", + "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", + "syn_derive", ] [[package]] @@ -762,6 +741,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.38" @@ -1634,8 +1619,8 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jmt" -version = "0.9.0" -source = "git+https://github.com/penumbra-zone/jmt.git?rev=1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6#1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6" +version = "0.10.0" +source = "git+https://github.com/penumbra-zone/jmt.git?rev=fd1c8ef#fd1c8ef99913663eb801576a9b13a31523861d87" dependencies = [ "anyhow", "borsh", @@ -1926,7 +1911,7 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -2000,15 +1985,6 @@ dependencies = [ "uint", ] -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - [[package]] name = "proc-macro-crate" version = "3.1.0" @@ -2889,6 +2865,7 @@ dependencies = [ "borsh", "derive_more", "digest 0.10.7", + "hashbrown 0.14.5", "hex", "jmt", "schemars", @@ -2936,6 +2913,7 @@ version = "0.4.0-rc.3" dependencies = [ "anyhow", "bincode", + "borsh", "bytemuck", "risc0-zkvm", "risc0-zkvm-platform", @@ -3113,6 +3091,18 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "synstructure" version = "0.13.1" @@ -3221,15 +3211,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml_datetime" version = "0.6.6" diff --git a/crates/bitcoin-da/src/helpers/test_utils.rs b/crates/bitcoin-da/src/helpers/test_utils.rs index 06ad67f7f..bf33a94f2 100644 --- a/crates/bitcoin-da/src/helpers/test_utils.rs +++ b/crates/bitcoin-da/src/helpers/test_utils.rs @@ -4,7 +4,7 @@ use bitcoin::block::{Header, Version}; use bitcoin::hash_types::{TxMerkleNode, WitnessMerkleNode}; use bitcoin::hashes::{sha256d, Hash}; use bitcoin::string::FromHexStr; -use bitcoin::{BlockHash, CompactTarget}; +use bitcoin::{BlockHash, CompactTarget, Transaction}; use sov_rollup_interface::da::{DaSpec, DaVerifier}; use crate::helpers::builders::decompress_blob; @@ -12,7 +12,6 @@ use crate::helpers::parsers::{parse_hex_transaction, parse_transaction}; use crate::spec::blob::BlobWithSender; use crate::spec::header::HeaderWrapper; use crate::spec::proof::InclusionMultiProof; -use crate::spec::transaction::Transaction; use crate::verifier::BitcoinVerifier; pub(crate) fn get_mock_txs() -> Vec { @@ -74,12 +73,15 @@ pub(crate) fn get_mock_data() -> ( let block_txs = get_mock_txs(); // relevant txs are on 6, 8, 10, 12 indices - let completeness_proof = vec![ + let completeness_proof = [ block_txs[6].clone(), block_txs[8].clone(), block_txs[10].clone(), block_txs[12].clone(), - ]; + ] + .into_iter() + .map(Into::into) + .collect(); let mut inclusion_proof = InclusionMultiProof { txids: block_txs @@ -90,7 +92,7 @@ pub(crate) fn get_mock_data() -> ( .iter() .map(|t| t.wtxid().to_byte_array()) .collect(), - coinbase_tx: block_txs[0].clone(), + coinbase_tx: block_txs[0].clone().into(), }; // Coinbase tx wtxid should be [0u8;32] diff --git a/crates/bitcoin-da/src/rpc.rs b/crates/bitcoin-da/src/rpc.rs index c139d3b2d..078156d6e 100644 --- a/crates/bitcoin-da/src/rpc.rs +++ b/crates/bitcoin-da/src/rpc.rs @@ -14,7 +14,7 @@ use tracing::{instrument, warn}; use crate::helpers::parsers::parse_hex_transaction; use crate::spec::block::BitcoinBlock; use crate::spec::header::HeaderWrapper; -use crate::spec::transaction::Transaction; +use crate::spec::transaction::TransactionWrapper; use crate::spec::utxo::UTXO; // RPCError is a struct that represents an error returned by the Bitcoin RPC @@ -145,7 +145,7 @@ impl BitcoinNode { self.call::("getbestblockhash", vec![]).await } - fn calculate_witness_root(txdata: &[Transaction]) -> Option { + fn calculate_witness_root(txdata: &[TransactionWrapper]) -> Option { let hashes = txdata.iter().enumerate().map(|(i, t)| { if i == 0 { // Replace the first hash with zeroes. @@ -161,16 +161,7 @@ impl BitcoinNode { pub async fn get_block_header(&self, hash: String) -> Result { // The full block is requested here because txs_commitment is the witness root let full_block = self.get_block(hash).await?; - let witness_root = Self::calculate_witness_root(&full_block.txdata).unwrap(); - - let header_wrapper: HeaderWrapper = HeaderWrapper::new( - *full_block.header.header(), - full_block.txdata.len() as u32, - full_block.header.height, - witness_root, - ); - - Ok(header_wrapper) + Ok(full_block.header) } // get_block returns the block at the given hash @@ -196,13 +187,14 @@ impl BitcoinNode { let txdata = full_block["tx"].as_array().unwrap(); - let txs: Vec = txdata + let txs: Vec = txdata .iter() .map(|tx| { let tx_hex = tx["hex"].as_str().unwrap(); parse_hex_transaction(tx_hex).unwrap() // hex from rpc cannot be invalid }) + .map(Into::into) .collect(); let witness_root = diff --git a/crates/bitcoin-da/src/service.rs b/crates/bitcoin-da/src/service.rs index 38710af15..2df83f42f 100644 --- a/crates/bitcoin-da/src/service.rs +++ b/crates/bitcoin-da/src/service.rs @@ -556,7 +556,7 @@ mod tests { use bitcoin::hash_types::{TxMerkleNode, WitnessMerkleNode}; use bitcoin::secp256k1::Keypair; use bitcoin::string::FromHexStr; - use bitcoin::{BlockHash, CompactTarget, Transaction}; + use bitcoin::{BlockHash, CompactTarget}; use sov_rollup_interface::da::DaVerifier; use sov_rollup_interface::services::da::{DaService, SlotData}; @@ -566,6 +566,7 @@ mod tests { use crate::service::DaServiceConfig; use crate::spec::block::BitcoinBlock; use crate::spec::header::HeaderWrapper; + use crate::spec::transaction::TransactionWrapper; use crate::spec::RollupParams; use crate::verifier::BitcoinVerifier; @@ -639,6 +640,7 @@ mod tests { let (header, _inclusion_proof, _completeness_proof, relevant_txs) = get_mock_data(); let block_txs = get_mock_txs(); + let block_txs = block_txs.into_iter().map(Into::into).collect(); let block = BitcoinBlock { header, @@ -660,6 +662,7 @@ mod tests { let da_service = get_service().await; let (header, _inclusion_proof, _completeness_proof, _relevant_txs) = get_mock_data(); let block_txs = get_mock_txs(); + let block_txs = block_txs.into_iter().map(Into::into).collect(); let block = BitcoinBlock { header, @@ -735,9 +738,10 @@ mod tests { let txs_str = std::fs::read_to_string("test_data/false_signature_txs.txt").unwrap(); - let txdata: Vec = txs_str + let txdata: Vec = txs_str .lines() .map(|tx| parse_hex_transaction(tx).unwrap()) + .map(Into::into) .collect(); let block = BitcoinBlock { header, txdata }; @@ -795,9 +799,10 @@ mod tests { let txs_str = std::fs::read_to_string("test_data/mock_txs.txt").unwrap(); - let txdata: Vec = txs_str + let txdata: Vec = txs_str .lines() .map(|tx| parse_hex_transaction(tx).unwrap()) + .map(Into::into) .collect(); let block = BitcoinBlock { header, txdata }; diff --git a/crates/bitcoin-da/src/spec/blob.rs b/crates/bitcoin-da/src/spec/blob.rs index 823a2cea0..3f501ddff 100644 --- a/crates/bitcoin-da/src/spec/blob.rs +++ b/crates/bitcoin-da/src/spec/blob.rs @@ -1,3 +1,4 @@ +use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; use sov_rollup_interface::da::{BlobReaderTrait, CountedBufReader}; use sov_rollup_interface::Buf; @@ -5,7 +6,7 @@ use sov_rollup_interface::Buf; use super::address::AddressWrapper; // BlobBuf is a wrapper around Vec to implement Buf -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] pub struct BlobBuf { pub data: Vec, @@ -40,7 +41,7 @@ impl Buf for BlobBuf { } // BlobWithSender is a wrapper around BlobBuf to implement BlobReaderTrait -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] pub struct BlobWithSender { pub hash: [u8; 32], diff --git a/crates/bitcoin-da/src/spec/block.rs b/crates/bitcoin-da/src/spec/block.rs index f68739764..12164be31 100644 --- a/crates/bitcoin-da/src/spec/block.rs +++ b/crates/bitcoin-da/src/spec/block.rs @@ -3,14 +3,14 @@ use sov_rollup_interface::da::BlockHeaderTrait; use sov_rollup_interface::services::da::SlotData; use super::header::HeaderWrapper; -use super::transaction::Transaction; +use super::transaction::TransactionWrapper; use crate::verifier::ChainValidityCondition; // BitcoinBlock is a wrapper around Block to remove unnecessary fields and implement SlotData #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BitcoinBlock { pub header: HeaderWrapper, - pub txdata: Vec, + pub txdata: Vec, } impl SlotData for BitcoinBlock { diff --git a/crates/bitcoin-da/src/spec/block_hash.rs b/crates/bitcoin-da/src/spec/block_hash.rs index 4f6b60d70..12fac6aff 100644 --- a/crates/bitcoin-da/src/spec/block_hash.rs +++ b/crates/bitcoin-da/src/spec/block_hash.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use bitcoin::hashes::Hash; use bitcoin::BlockHash; +use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; use sov_rollup_interface::da::BlockHashTrait; @@ -11,12 +12,31 @@ pub struct BlockHashWrapper(pub BlockHash); impl BlockHashTrait for BlockHashWrapper {} +impl BorshSerialize for BlockHashWrapper { + fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { + BorshSerialize::serialize(&self.0.to_byte_array(), writer) + } +} + +impl BorshDeserialize for BlockHashWrapper { + fn deserialize_reader(reader: &mut R) -> borsh::io::Result { + let hash = BorshDeserialize::deserialize_reader(reader)?; + Ok(BlockHashWrapper(BlockHash::from_byte_array(hash))) + } +} + impl From for [u8; 32] { fn from(val: BlockHashWrapper) -> Self { val.0.as_raw_hash().to_byte_array() } } +impl From<[u8; 32]> for BlockHashWrapper { + fn from(val: [u8; 32]) -> Self { + BlockHashWrapper(BlockHash::from_byte_array(val)) + } +} + impl AsRef<[u8]> for BlockHashWrapper { fn as_ref(&self) -> &[u8] { self.0.as_ref() diff --git a/crates/bitcoin-da/src/spec/header.rs b/crates/bitcoin-da/src/spec/header.rs index 94901c8bd..42c896d7c 100644 --- a/crates/bitcoin-da/src/spec/header.rs +++ b/crates/bitcoin-da/src/spec/header.rs @@ -1,33 +1,40 @@ -use bitcoin::block::Header; -use bitcoin::hash_types::{TxMerkleNode, WitnessMerkleNode}; +use core::ops::Deref; + +use bitcoin::block::Header as BitcoinHeader; +use bitcoin::consensus::{Decodable, Encodable}; +use bitcoin::hash_types::WitnessMerkleNode; +use bitcoin::hashes::Hash; use bitcoin::BlockHash; +use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; use sov_rollup_interface::da::BlockHeaderTrait; use super::block_hash::BlockHashWrapper; -// BlockHashWrapper is a wrapper around BlockHash to implement BlockHashTrait -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +// HeaderWrapper is a wrapper around BlockHash to implement BlockHeaderTrait +#[derive( + Clone, Debug, PartialEq, Eq, Hash, BorshDeserialize, BorshSerialize, Serialize, Deserialize, +)] pub struct HeaderWrapper { - header: Header, // not pub to prevent uses like block.header.header.merkle_root + header: BitcoinHeaderWrapper, // not pub to prevent uses like block.header.header.merkle_root pub tx_count: u32, pub height: u64, - txs_commitment: WitnessMerkleNode, + txs_commitment: [u8; 32], } impl BlockHeaderTrait for HeaderWrapper { type Hash = BlockHashWrapper; fn prev_hash(&self) -> Self::Hash { - BlockHashWrapper(self.header.prev_blockhash) + BlockHashWrapper::from(self.header.prev_blockhash.to_byte_array()) } fn hash(&self) -> Self::Hash { - BlockHashWrapper(self.header.block_hash()) + BlockHashWrapper::from(self.header.block_hash().to_byte_array()) } fn txs_commitment(&self) -> Self::Hash { - BlockHashWrapper(BlockHash::from_raw_hash(self.txs_commitment.into())) + BlockHashWrapper::from(self.txs_commitment) } fn height(&self) -> u64 { @@ -41,16 +48,16 @@ impl BlockHeaderTrait for HeaderWrapper { impl HeaderWrapper { pub fn new( - header: Header, + header: BitcoinHeader, tx_count: u32, height: u64, txs_commitment: WitnessMerkleNode, ) -> Self { Self { - header, + header: header.into(), tx_count, height, - txs_commitment, + txs_commitment: txs_commitment.to_byte_array(), } } @@ -58,11 +65,46 @@ impl HeaderWrapper { self.header.block_hash() } - pub fn merkle_root(&self) -> TxMerkleNode { - self.header.merkle_root + pub fn merkle_root(&self) -> [u8; 32] { + self.header.merkle_root.to_byte_array() } +} + +/// BitcoinHeaderWrapper is a wrapper around BitcoinHeaderWrapper to implement borsh serde +#[derive(Clone, PartialEq, Eq, Debug, Hash, Deserialize, Serialize)] +#[repr(transparent)] +#[serde(transparent)] +pub struct BitcoinHeaderWrapper { + header: BitcoinHeader, +} + +impl BorshSerialize for BitcoinHeaderWrapper { + #[inline] + fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { + Encodable::consensus_encode(&self.header, writer) + .expect("Bitcoin Header serialization cannot fail"); + Ok(()) + } +} - pub fn header(&self) -> &Header { +impl BorshDeserialize for BitcoinHeaderWrapper { + #[inline] + fn deserialize_reader(reader: &mut R) -> borsh::io::Result { + let header = Decodable::consensus_decode(reader) + .expect("Bitcoin Header deserialization cannot fail"); + Ok(Self { header }) + } +} + +impl Deref for BitcoinHeaderWrapper { + type Target = BitcoinHeader; + fn deref(&self) -> &Self::Target { &self.header } } + +impl From for BitcoinHeaderWrapper { + fn from(header: BitcoinHeader) -> Self { + Self { header } + } +} diff --git a/crates/bitcoin-da/src/spec/mod.rs b/crates/bitcoin-da/src/spec/mod.rs index f038e20ee..eb8cabf8a 100644 --- a/crates/bitcoin-da/src/spec/mod.rs +++ b/crates/bitcoin-da/src/spec/mod.rs @@ -1,4 +1,5 @@ -use bitcoin::Transaction; +use borsh::{BorshDeserialize, BorshSerialize}; +use serde::{Deserialize, Serialize}; use sov_rollup_interface::da::DaSpec; use self::address::AddressWrapper; @@ -6,6 +7,7 @@ use self::blob::BlobWithSender; use self::block_hash::BlockHashWrapper; use self::header::HeaderWrapper; use self::proof::InclusionMultiProof; +use self::transaction::TransactionWrapper; use crate::verifier::ChainValidityCondition; pub mod address; @@ -19,7 +21,7 @@ pub mod proof; pub mod transaction; pub mod utxo; -#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)] +#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct BitcoinSpec; pub struct RollupParams { @@ -40,7 +42,7 @@ impl DaSpec for BitcoinSpec { type InclusionMultiProof = InclusionMultiProof; - type CompletenessProof = Vec; + type CompletenessProof = Vec; type ValidityCondition = ChainValidityCondition; } diff --git a/crates/bitcoin-da/src/spec/proof.rs b/crates/bitcoin-da/src/spec/proof.rs index 49f49474c..460918110 100644 --- a/crates/bitcoin-da/src/spec/proof.rs +++ b/crates/bitcoin-da/src/spec/proof.rs @@ -1,20 +1,21 @@ -use bitcoin::absolute::{LockTime, Time}; -use bitcoin::Transaction; +use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; +use crate::spec::TransactionWrapper; + // Set of proofs for inclusion of a transaction in a block -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, Serialize, Deserialize)] pub struct InclusionMultiProof { pub txids: Vec<[u8; 32]>, pub wtxids: Vec<[u8; 32]>, - pub coinbase_tx: Transaction, + pub coinbase_tx: TransactionWrapper, } impl InclusionMultiProof { pub(crate) fn new( txids: Vec<[u8; 32]>, wtxids: Vec<[u8; 32]>, - coinbase_tx: Transaction, + coinbase_tx: TransactionWrapper, ) -> Self { InclusionMultiProof { txids, @@ -29,12 +30,7 @@ impl Default for InclusionMultiProof { InclusionMultiProof { txids: vec![], wtxids: vec![], - coinbase_tx: Transaction { - version: bitcoin::transaction::Version(0), - lock_time: LockTime::Seconds(Time::MIN), - input: vec![], - output: vec![], - }, + coinbase_tx: TransactionWrapper::empty(), } } } diff --git a/crates/bitcoin-da/src/spec/transaction.rs b/crates/bitcoin-da/src/spec/transaction.rs index 1d9dde9da..e28b52179 100644 --- a/crates/bitcoin-da/src/spec/transaction.rs +++ b/crates/bitcoin-da/src/spec/transaction.rs @@ -1,2 +1,64 @@ -// pub use bitcoin::Transaction; -pub type Transaction = bitcoin::Transaction; +use core::ops::{Deref, DerefMut}; + +use bitcoin::absolute::{LockTime, Time}; +use bitcoin::consensus::{Decodable, Encodable}; +use bitcoin::Transaction as BitcoinTransaction; +use borsh::{BorshDeserialize, BorshSerialize}; +use serde::{Deserialize, Serialize}; + +/// TransactionWrapper is a wrapper around BlockHash to implement borsh serde +#[derive(Clone, PartialEq, Eq, Debug, Hash, Deserialize, Serialize)] +#[repr(transparent)] +#[serde(transparent)] +pub struct TransactionWrapper { + tx: BitcoinTransaction, +} + +impl TransactionWrapper { + pub fn empty() -> Self { + let tx = BitcoinTransaction { + version: bitcoin::transaction::Version(0), + lock_time: LockTime::Seconds(Time::MIN), + input: vec![], + output: vec![], + }; + Self { tx } + } +} + +impl BorshSerialize for TransactionWrapper { + #[inline] + fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { + Encodable::consensus_encode(&self.tx, writer) + .expect("Bitcoin Transaction serialization cannot fail"); + Ok(()) + } +} + +impl BorshDeserialize for TransactionWrapper { + #[inline] + fn deserialize_reader(reader: &mut R) -> borsh::io::Result { + let tx = Decodable::consensus_decode(reader) + .expect("Bitcoin Transaction deserialization cannot fail"); + Ok(Self { tx }) + } +} + +impl Deref for TransactionWrapper { + type Target = BitcoinTransaction; + fn deref(&self) -> &Self::Target { + &self.tx + } +} + +impl DerefMut for TransactionWrapper { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.tx + } +} + +impl From for TransactionWrapper { + fn from(tx: BitcoinTransaction) -> Self { + Self { tx } + } +} diff --git a/crates/bitcoin-da/src/verifier.rs b/crates/bitcoin-da/src/verifier.rs index 1ca7c5d66..e6e447637 100644 --- a/crates/bitcoin-da/src/verifier.rs +++ b/crates/bitcoin-da/src/verifier.rs @@ -104,7 +104,7 @@ impl DaVerifier for BitcoinVerifier { // verify that one of the outputs of the coinbase transaction has script pub key starting with 0x6a24aa21a9ed, // and the rest of the script pub key is the commitment of witness data. if !completeness_proof.is_empty() { - let coinbase_tx = inclusion_proof.coinbase_tx.clone(); + let coinbase_tx = &inclusion_proof.coinbase_tx; // If there are more than one scriptPubKey matching the pattern, // the one with highest output index is assumed to be the commitment. // That is why the iterator is reversed. @@ -178,7 +178,7 @@ impl DaVerifier for BitcoinVerifier { let mut completeness_tx_hashes = HashSet::new(); for (index_completeness, tx) in completeness_proof.iter().enumerate() { - let txid = tx.txid().to_raw_hash().to_byte_array(); + let txid = tx.txid().to_byte_array(); // make sure it starts with the correct prefix if !txid.starts_with(prefix) { @@ -252,7 +252,7 @@ impl DaVerifier for BitcoinVerifier { return Err(ValidationError::NonRelevantTxInProof); } - let tx_root = block_header.merkle_root().to_raw_hash().to_byte_array(); + let tx_root = block_header.merkle_root(); // Inclusion proof is all the txs in the block. let tx_hashes = inclusion_proof @@ -299,6 +299,7 @@ mod tests { use crate::spec::blob::BlobWithSender; use crate::spec::header::HeaderWrapper; use crate::spec::proof::InclusionMultiProof; + use crate::spec::transaction::TransactionWrapper; use crate::spec::RollupParams; use crate::verifier::{ChainValidityCondition, ValidationError}; @@ -351,6 +352,7 @@ mod tests { ); let block_txs = get_non_segwit_mock_txs(); + let block_txs: Vec = block_txs.into_iter().map(Into::into).collect(); // block does not have any segwit txs let idx = block_txs[0].output.iter().position(|output| { @@ -424,17 +426,22 @@ mod tests { .unwrap(), ); - let mut block_txs = get_mock_txs(); + let block_txs = get_mock_txs(); + let mut block_txs: Vec = + block_txs.into_iter().map(Into::into).collect(); block_txs[0].input[0].witness = Witness::from_slice(&[vec![1u8; 32]]); // relevant txs are on 6, 8, 10, 12 indices - let completeness_proof = vec![ + let completeness_proof = [ block_txs[6].clone(), block_txs[8].clone(), block_txs[10].clone(), block_txs[12].clone(), - ]; + ] + .into_iter() + .map(Into::into) + .collect(); let mut inclusion_proof = InclusionMultiProof { txids: block_txs @@ -499,7 +506,9 @@ mod tests { .unwrap(), ); - let mut block_txs = get_mock_txs(); + let block_txs = get_mock_txs(); + let mut block_txs: Vec = + block_txs.into_iter().map(Into::into).collect(); let idx = block_txs[0] .output @@ -520,12 +529,15 @@ mod tests { ]); // relevant txs are on 6, 8, 10, 12 indices - let completeness_proof = vec![ + let completeness_proof = [ block_txs[6].clone(), block_txs[8].clone(), block_txs[10].clone(), block_txs[12].clone(), - ]; + ] + .into_iter() + .map(Into::into) + .collect(); let mut inclusion_proof = InclusionMultiProof { txids: block_txs @@ -590,7 +602,9 @@ mod tests { .unwrap(), ); - let mut block_txs = get_mock_txs(); + let block_txs = get_mock_txs(); + let mut block_txs: Vec = + block_txs.into_iter().map(Into::into).collect(); // This is the changed witness of the 6th tx, the first byte of script is changed from 32 to 33 // This creates a different wtxid, thus the verification should fail @@ -631,12 +645,15 @@ mod tests { block_txs[6].input[0].witness = Witness::from_slice(&changed_witness); // relevant txs are on 6, 8, 10, 12 indices - let completeness_proof = vec![ + let completeness_proof = [ block_txs[6].clone(), block_txs[8].clone(), block_txs[10].clone(), block_txs[12].clone(), - ]; + ] + .into_iter() + .map(Into::into) + .collect(); let mut inclusion_proof = InclusionMultiProof { txids: block_txs @@ -857,7 +874,7 @@ mod tests { let (block_header, inclusion_proof, mut completeness_proof, txs) = get_mock_data(); - completeness_proof.push(get_mock_txs().get(1).unwrap().clone()); + completeness_proof.push(get_mock_txs().get(1).unwrap().clone().into()); assert_eq!( verifier.verify_relevant_tx_list( @@ -969,11 +986,9 @@ mod tests { }); let (block_header, inclusion_proof, completeness_proof, mut txs) = get_mock_data(); - + let tx1 = &completeness_proof[1]; txs[1] = BlobWithSender::new( - parse_transaction(&completeness_proof[1], "sov-btc") - .unwrap() - .body, + parse_transaction(tx1, "sov-btc").unwrap().body, vec![2; 33], txs[1].hash, ); diff --git a/crates/evm/src/tests/utils.rs b/crates/evm/src/tests/utils.rs index 863c16200..e6d79f724 100644 --- a/crates/evm/src/tests/utils.rs +++ b/crates/evm/src/tests/utils.rs @@ -87,10 +87,10 @@ pub(crate) fn commit( // Save checkpoint let mut checkpoint = working_set.checkpoint(); - let (cache_log, witness) = checkpoint.freeze(); + let (cache_log, mut witness) = checkpoint.freeze(); let (root, authenticated_node_batch, _) = storage - .compute_state_update(cache_log, &witness) + .compute_state_update(cache_log, &mut witness) .expect("jellyfish merkle tree update must succeed"); let working_set = checkpoint.to_revertable(); diff --git a/crates/fullnode/src/runner.rs b/crates/fullnode/src/runner.rs index 2152ff68f..e9cdff4c7 100644 --- a/crates/fullnode/src/runner.rs +++ b/crates/fullnode/src/runner.rs @@ -7,7 +7,6 @@ use anyhow::{anyhow, bail}; use backoff::future::retry as retry_backoff; use backoff::ExponentialBackoffBuilder; use borsh::de::BorshDeserialize; -use borsh::BorshSerialize as _; use jsonrpsee::core::client::Error as JsonrpseeError; use jsonrpsee::RpcModule; use lru::LruCache; @@ -277,7 +276,7 @@ where da_slot_hash: state_transition.da_slot_hash.clone().into(), sequencer_public_key: state_transition.sequencer_public_key, sequencer_da_public_key: state_transition.sequencer_da_public_key, - validity_condition: state_transition.validity_condition.try_to_vec().unwrap(), + validity_condition: borsh::to_vec(&state_transition.validity_condition).unwrap(), }; let l1_hash = state_transition.da_slot_hash.into(); diff --git a/crates/prover/src/runner.rs b/crates/prover/src/runner.rs index 1a910829a..7b5c5eb19 100644 --- a/crates/prover/src/runner.rs +++ b/crates/prover/src/runner.rs @@ -7,7 +7,6 @@ use anyhow::bail; use backoff::future::retry as retry_backoff; use backoff::ExponentialBackoffBuilder; use borsh::de::BorshDeserialize; -use borsh::BorshSerialize; use jsonrpsee::core::client::Error as JsonrpseeError; use jsonrpsee::RpcModule; use rand::Rng; @@ -573,7 +572,7 @@ where da_slot_hash: transition_data.da_slot_hash.into(), sequencer_public_key: transition_data.sequencer_public_key, sequencer_da_public_key: transition_data.sequencer_da_public_key, - validity_condition: transition_data.validity_condition.try_to_vec().unwrap(), + validity_condition: borsh::to_vec(&transition_data.validity_condition).unwrap(), }; match pg_client.as_ref() { diff --git a/crates/sequencer/src/sequencer.rs b/crates/sequencer/src/sequencer.rs index 7eff7f6a9..5301ff60a 100644 --- a/crates/sequencer/src/sequencer.rs +++ b/crates/sequencer/src/sequencer.rs @@ -7,7 +7,6 @@ use std::time::Duration; use std::vec; use anyhow::anyhow; -use borsh::ser::BorshSerialize; use citrea_evm::{CallMessage, Evm, RlpEvmTransaction, MIN_TRANSACTION_GAS}; use citrea_stf::runtime::Runtime; use digest::Digest; @@ -362,10 +361,7 @@ where ); let timestamp = chrono::Local::now().timestamp() as u64; - let pub_key = self - .sov_tx_signer_priv_key - .pub_key() - .try_to_vec() + let pub_key = borsh::to_vec(&self.sov_tx_signer_priv_key.pub_key()) .map_err(Into::::into)?; let deposit_data = self @@ -629,8 +625,7 @@ where debug!("Sequencer: submitting commitment: {:?}", commitment); - let blob = DaData::SequencerCommitment(commitment.clone()) - .try_to_vec() + let blob = borsh::to_vec(&DaData::SequencerCommitment(commitment.clone())) .map_err(|e| anyhow!(e))?; let (notify, rx) = oneshot_channel(); let request = BlobWithNotifier { blob, notify }; @@ -943,9 +938,9 @@ where // TODO: figure out what to do with sov-tx fields // chain id gas tip and gas limit - Transaction::::new_signed_tx(&self.sov_tx_signer_priv_key, raw_message, 0, nonce) - .try_to_vec() - .map_err(|e| anyhow!(e)) + let transaction = + Transaction::::new_signed_tx(&self.sov_tx_signer_priv_key, raw_message, 0, nonce); + borsh::to_vec(&transaction).map_err(|e| anyhow!(e)) } /// Signs necessary info and returns a BlockTemplate @@ -953,12 +948,12 @@ where &mut self, soft_confirmation: UnsignedSoftConfirmationBatch, ) -> anyhow::Result { - let raw = soft_confirmation.try_to_vec().map_err(|e| anyhow!(e))?; + let raw = borsh::to_vec(&soft_confirmation).map_err(|e| anyhow!(e))?; let hash = ::Hasher::digest(raw.as_slice()).into(); let signature = self.sov_tx_signer_priv_key.sign(&raw); - + let pub_key = self.sov_tx_signer_priv_key.pub_key(); Ok(SignedSoftConfirmationBatch::new( hash, soft_confirmation.da_slot_height(), @@ -968,11 +963,8 @@ where soft_confirmation.l1_fee_rate(), soft_confirmation.txs(), soft_confirmation.deposit_data(), - signature.try_to_vec().map_err(|e| anyhow!(e))?, - self.sov_tx_signer_priv_key - .pub_key() - .try_to_vec() - .map_err(|e| anyhow!(e))?, + borsh::to_vec(&signature).map_err(|e| anyhow!(e))?, + borsh::to_vec(&pub_key).map_err(|e| anyhow!(e))?, soft_confirmation.timestamp(), )) } diff --git a/crates/sovereign-sdk/adapters/mock-da/src/service.rs b/crates/sovereign-sdk/adapters/mock-da/src/service.rs index f457be933..c2c0bcd4e 100644 --- a/crates/sovereign-sdk/adapters/mock-da/src/service.rs +++ b/crates/sovereign-sdk/adapters/mock-da/src/service.rs @@ -1,6 +1,6 @@ use std::path::Path; use std::pin::Pin; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; use std::task::{Context, Poll}; use std::time::Duration; @@ -8,7 +8,6 @@ use async_trait::async_trait; use pin_project::pin_project; use sha2::Digest; use sov_rollup_interface::da::{BlockHeaderTrait, DaSpec, Time}; -use sov_rollup_interface::maybestd::sync::Arc; use sov_rollup_interface::services::da::{BlobWithNotifier, DaService, SlotData}; use tokio::sync::mpsc::{unbounded_channel, UnboundedSender}; use tokio::sync::{broadcast, Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard}; diff --git a/crates/sovereign-sdk/adapters/mock-da/src/types/address.rs b/crates/sovereign-sdk/adapters/mock-da/src/types/address.rs index caf8c55db..a813f67e6 100644 --- a/crates/sovereign-sdk/adapters/mock-da/src/types/address.rs +++ b/crates/sovereign-sdk/adapters/mock-da/src/types/address.rs @@ -100,8 +100,6 @@ impl RollupAddress for MockAddress {} #[cfg(test)] mod tests { - use sov_rollup_interface::maybestd::string::ToString; - use super::*; #[test] diff --git a/crates/sovereign-sdk/adapters/mock-da/src/types/mod.rs b/crates/sovereign-sdk/adapters/mock-da/src/types/mod.rs index 795414cba..336021447 100644 --- a/crates/sovereign-sdk/adapters/mock-da/src/types/mod.rs +++ b/crates/sovereign-sdk/adapters/mock-da/src/types/mod.rs @@ -68,7 +68,7 @@ impl std::hash::Hash for MockHash { impl BlockHashTrait for MockHash {} /// A mock block header used for testing. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] +#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct MockBlockHeader { /// The hash of the previous block. pub prev_hash: MockHash, diff --git a/crates/sovereign-sdk/adapters/mock-da/src/verifier.rs b/crates/sovereign-sdk/adapters/mock-da/src/verifier.rs index 4940b8d7a..94fcef53a 100644 --- a/crates/sovereign-sdk/adapters/mock-da/src/verifier.rs +++ b/crates/sovereign-sdk/adapters/mock-da/src/verifier.rs @@ -1,3 +1,5 @@ +use borsh::{BorshDeserialize, BorshSerialize}; +use serde::{Deserialize, Serialize}; use sov_rollup_interface::da::{BlobReaderTrait, DaSpec, DaVerifier}; use crate::{MockAddress, MockBlob, MockBlockHeader, MockDaVerifier, MockHash, MockValidityCond}; @@ -29,7 +31,7 @@ impl BlobReaderTrait for MockBlob { } /// A [`sov_rollup_interface::da::DaSpec`] suitable for testing. -#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)] +#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct MockDaSpec; impl DaSpec for MockDaSpec { diff --git a/crates/sovereign-sdk/adapters/mock-zkvm/src/lib.rs b/crates/sovereign-sdk/adapters/mock-zkvm/src/lib.rs index d9646a471..c930f5832 100644 --- a/crates/sovereign-sdk/adapters/mock-zkvm/src/lib.rs +++ b/crates/sovereign-sdk/adapters/mock-zkvm/src/lib.rs @@ -23,22 +23,22 @@ impl Matches for MockCodeCommitment { /// A mock proof generated by a zkVM. #[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Serialize, Deserialize)] -pub struct MockProof<'a> { +pub struct MockProof { /// The ID of the program this proof might be valid for. pub program_id: MockCodeCommitment, /// Whether the proof is valid. pub is_valid: bool, /// The tamper-proof outputs of the proof. - pub log: &'a [u8], + pub log: Vec, } -impl<'a> MockProof<'a> { +impl MockProof { /// Serializes a proof into a writer. pub fn encode(&self, mut writer: impl Write) { writer.write_all(&self.program_id.0).unwrap(); let is_valid_byte = if self.is_valid { 1 } else { 0 }; writer.write_all(&[is_valid_byte]).unwrap(); - writer.write_all(self.log).unwrap(); + writer.write_all(&self.log).unwrap(); } /// Serializes a proof into a vector. @@ -49,11 +49,11 @@ impl<'a> MockProof<'a> { } /// Tries to deserialize a proof from a byte slice. - pub fn decode(input: &'a [u8]) -> Result { + pub fn decode(input: &[u8]) -> Result { ensure!(input.len() >= 33, "Input is too short"); let program_id = MockCodeCommitment(input[0..32].try_into().unwrap()); let is_valid = input[32] == 1; - let log = &input[33..]; + let log = input[33..].to_vec(); Ok(Self { program_id, is_valid, @@ -132,7 +132,7 @@ impl sov_rollup_interface::zk::Zkvm for MockZkv "Proof failed to verify against requested code commitment" ); anyhow::ensure!(proof.is_valid, "Proof is not valid"); - Ok(proof.log) + Ok(&serialized_proof[33..]) } fn verify_and_extract_output< @@ -152,14 +152,14 @@ impl sov_rollup_interface::zk::ZkvmHost { type Guest = MockZkGuest; - fn add_hint(&mut self, item: T) { - let hint = bincode::serialize(&item).unwrap(); + fn add_hint(&mut self, item: T) { + let hint = borsh::to_vec(&item).unwrap(); let proof_info = ProofInfo { hint, validity_condition: self.validity_condition, }; - let data = bincode::serialize(&proof_info).unwrap(); + let data = borsh::to_vec(&proof_info).unwrap(); self.committed_data.push_back(data) } @@ -173,16 +173,14 @@ impl sov_rollup_interface::zk::ZkvmHost Ok(sov_rollup_interface::zk::Proof::PublicInput(data)) } - fn extract_output< - Da: sov_rollup_interface::da::DaSpec, - Root: Serialize + serde::de::DeserializeOwned, - >( + fn extract_output( proof: &sov_rollup_interface::zk::Proof, ) -> Result, Self::Error> { match proof { sov_rollup_interface::zk::Proof::PublicInput(pub_input) => { let data: ProofInfo = bincode::deserialize(pub_input)?; - let st: StateTransitionData = bincode::deserialize(&data.hint)?; + let st: StateTransitionData = + BorshDeserialize::deserialize(&mut &*data.hint)?; Ok(sov_rollup_interface::zk::StateTransition { initial_state_root: st.initial_state_root, @@ -228,16 +226,16 @@ impl sov_rollup_interface::zk::Zkvm for MockZkGuest { } impl sov_rollup_interface::zk::ZkvmGuest for MockZkGuest { - fn read_from_host(&self) -> T { + fn read_from_host(&self) -> T { unimplemented!() } - fn commit(&self, _item: &T) { + fn commit(&self, _item: &T) { unimplemented!() } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, BorshDeserialize, BorshSerialize, Serialize, Deserialize)] struct ProofInfo { hint: Vec, validity_condition: ValidityCond, @@ -248,7 +246,7 @@ fn test_mock_proof_round_trip() { let proof = MockProof { program_id: MockCodeCommitment([1; 32]), is_valid: true, - log: &[2; 50], + log: vec![2; 50], }; let mut encoded = Vec::new(); diff --git a/crates/sovereign-sdk/adapters/risc0-bonsai/Cargo.toml b/crates/sovereign-sdk/adapters/risc0-bonsai/Cargo.toml index 0e6ef1617..8c6c0239d 100644 --- a/crates/sovereign-sdk/adapters/risc0-bonsai/Cargo.toml +++ b/crates/sovereign-sdk/adapters/risc0-bonsai/Cargo.toml @@ -14,6 +14,7 @@ readme = "README.md" [dependencies] anyhow = { workspace = true } bincode = { workspace = true } +borsh = { workspace = true } risc0-zkvm = { workspace = true, default-features = false, features = ["std"] } risc0-zkvm-platform = { workspace = true } risc0-zkp = { workspace = true, optional = true } diff --git a/crates/sovereign-sdk/adapters/risc0-bonsai/src/host.rs b/crates/sovereign-sdk/adapters/risc0-bonsai/src/host.rs index b9ac82299..ac260dfab 100644 --- a/crates/sovereign-sdk/adapters/risc0-bonsai/src/host.rs +++ b/crates/sovereign-sdk/adapters/risc0-bonsai/src/host.rs @@ -6,7 +6,7 @@ use std::time::Duration; use anyhow::anyhow; use bonsai_sdk::alpha as bonsai_sdk; -use risc0_zkvm::serde::to_vec; +use borsh::{BorshDeserialize, BorshSerialize}; use risc0_zkvm::sha::Digest; use risc0_zkvm::{ compute_image_id, ExecutorEnvBuilder, ExecutorImpl, Groth16Receipt, InnerReceipt, Journal, @@ -142,7 +142,7 @@ impl BonsaiClient { let _ = notify.send(res); } BonsaiRequest::Download { url, notify } => { - debug!(%url, "Bonsai:upload_input"); + debug!(%url, "Bonsai:download"); let res = client.download(&url); let res = unwrap_bonsai_response!(res, 'client, 'queue); let _ = notify.send(res); @@ -325,14 +325,26 @@ impl<'a> Risc0BonsaiHost<'a> { } } - fn add_hint_bonsai(&mut self, item: T) { + fn add_hint_bonsai(&mut self, item: T) { // For running in "prove" mode. // Prepare input data and upload it. let client = self.client.as_ref().unwrap(); - let input_data = to_vec(&item).unwrap(); - let input_data = bytemuck::cast_slice(&input_data).to_vec(); + let mut input_data = vec![]; + let mut buf = borsh::to_vec(&item).unwrap(); + // append [0..] alignment + let rem = buf.len() % 4; + if rem > 0 { + buf.extend(vec![0; 4 - rem]); + } + let buf_u32: &[u32] = bytemuck::cast_slice(&buf); + // write len(u64) in LE + let len = buf_u32.len() as u64; + input_data.extend(len.to_le_bytes()); + // write buf + input_data.extend(buf); + // handle error let input_id = client.upload_input(input_data); tracing::info!("Uploaded input with id: {}", input_id); @@ -343,21 +355,23 @@ impl<'a> Risc0BonsaiHost<'a> { impl<'a> ZkvmHost for Risc0BonsaiHost<'a> { type Guest = Risc0Guest; - fn add_hint(&mut self, item: T) { + fn add_hint(&mut self, item: T) { // For running in "execute" mode. - // We use the in-memory size of `item` as an indication of how much - // space to reserve. This is in no way guaranteed to be exact, but - // usually the in-memory size and serialized data size are quite close. - // - // Note: this is just an optimization to avoid frequent reallocations, - // it's not actually required. - self.env - .reserve(std::mem::size_of::() / std::mem::size_of::()); - - let mut serializer = risc0_zkvm::serde::Serializer::new(&mut self.env); - item.serialize(&mut serializer) - .expect("Risc0 hint serialization is infallible"); + let mut buf = borsh::to_vec(&item).expect("Risc0 hint serialization is infallible"); + // append [0..] alignment to cast &[u8] to &[u32] + let rem = buf.len() % 4; + if rem > 0 { + buf.extend(vec![0; 4 - rem]); + } + let buf: &[u32] = bytemuck::cast_slice(&buf); + // write len(u64) in LE + let len = buf.len() as u64; + let len_buf = &len.to_le_bytes()[..]; + let len_buf: &[u32] = bytemuck::cast_slice(len_buf); + self.env.extend_from_slice(len_buf); + // write buf + self.env.extend_from_slice(buf); if self.client.is_some() { self.add_hint_bonsai(item) @@ -494,19 +508,20 @@ impl<'a> ZkvmHost for Risc0BonsaiHost<'a> { } } - fn extract_output( + fn extract_output( proof: &Proof, ) -> Result, Self::Error> { - match proof { + let journal = match proof { Proof::PublicInput(journal) => { let journal: Journal = bincode::deserialize(journal)?; - Ok(journal.decode()?) + journal } Proof::Full(data) => { let receipt: Receipt = bincode::deserialize(data)?; - Ok(receipt.journal.decode()?) + receipt.journal } - } + }; + Ok(BorshDeserialize::try_from_slice(&journal.bytes)?) } } diff --git a/crates/sovereign-sdk/adapters/risc0-bonsai/tests/native.rs b/crates/sovereign-sdk/adapters/risc0-bonsai/tests/native.rs index 6075b9b56..2b902a83c 100644 --- a/crates/sovereign-sdk/adapters/risc0-bonsai/tests/native.rs +++ b/crates/sovereign-sdk/adapters/risc0-bonsai/tests/native.rs @@ -1,8 +1,8 @@ -use serde::{Deserialize, Serialize}; +use borsh::{BorshDeserialize, BorshSerialize}; use sov_risc0_adapter::host::Risc0Host; use sov_rollup_interface::zk::{ZkvmGuest, ZkvmHost}; -#[derive(Serialize, Deserialize, Debug, PartialEq)] +#[derive(BorshDeserialize, BorshSerialize, Debug, PartialEq)] struct TestStruct { ints: Vec, string: String, @@ -13,12 +13,12 @@ fn test_hints_roundtrip() { let mut host = Risc0Host::new(&[]); let hint_a = TestStruct { - ints: vec![1, 2, 3, 4, 5], + ints: vec![0, 1, 2, 3, 4], string: "hello".to_string(), }; let hint_b = TestStruct { - ints: vec![1, 2, 3, 4, 5], - string: "hello".to_string(), + ints: vec![5, 6, 7, 8, 9], + string: "world".to_string(), }; host.add_hint(&hint_a); diff --git a/crates/sovereign-sdk/adapters/risc0/Cargo.toml b/crates/sovereign-sdk/adapters/risc0/Cargo.toml index bdf8ddfb6..774786a64 100644 --- a/crates/sovereign-sdk/adapters/risc0/Cargo.toml +++ b/crates/sovereign-sdk/adapters/risc0/Cargo.toml @@ -14,6 +14,7 @@ readme = "README.md" [dependencies] anyhow = { workspace = true } bincode = { workspace = true } +borsh = { workspace = true } risc0-zkvm = { workspace = true, default-features = false, features = ["std"] } risc0-zkvm-platform = { workspace = true } risc0-zkp = { workspace = true, optional = true } diff --git a/crates/sovereign-sdk/adapters/risc0/src/guest.rs b/crates/sovereign-sdk/adapters/risc0/src/guest.rs deleted file mode 100644 index e13c03b6e..000000000 --- a/crates/sovereign-sdk/adapters/risc0/src/guest.rs +++ /dev/null @@ -1,136 +0,0 @@ -//! This module implements the `ZkvmGuest` trait for the RISC0 VM. -#[cfg(not(target_os = "zkvm"))] -use std::ops::DerefMut; - -#[cfg(target_os = "zkvm")] -use risc0_zkvm::guest::env; -#[cfg(not(target_os = "zkvm"))] -use risc0_zkvm::serde::{Deserializer, WordRead}; -use serde::de::DeserializeOwned; -use serde::Serialize; -use sov_rollup_interface::zk::{Zkvm, ZkvmGuest}; - -use crate::Risc0MethodId; - -#[cfg(target_os = "zkvm")] -impl ZkvmGuest for Risc0Guest { - fn read_from_host(&self) -> T { - env::read() - } - - fn commit(&self, item: &T) { - env::commit(item); - } -} - -#[cfg(not(target_os = "zkvm"))] -#[derive(Default)] -struct Hints { - values: Vec, - position: usize, -} - -#[cfg(not(target_os = "zkvm"))] -impl Hints { - pub fn with_hints(hints: Vec) -> Self { - Hints { - values: hints, - position: 0, - } - } -} - -#[cfg(not(target_os = "zkvm"))] -impl WordRead for Hints { - fn read_words(&mut self, words: &mut [u32]) -> risc0_zkvm::serde::Result<()> { - if let Some(slice) = self.values.get(self.position..self.position + words.len()) { - words.copy_from_slice(slice); - self.position += words.len(); - Ok(()) - } else { - Err(risc0_zkvm::serde::Error::DeserializeUnexpectedEnd) - } - } - - fn read_padded_bytes(&mut self, bytes: &mut [u8]) -> risc0_zkvm::serde::Result<()> { - use risc0_zkvm::align_up; - use risc0_zkvm_platform::WORD_SIZE; - - let remaining_bytes: &[u8] = bytemuck::cast_slice(&self.values[self.position..]); - if bytes.len() > remaining_bytes.len() { - return Err(risc0_zkvm::serde::Error::DeserializeUnexpectedEnd); - } - bytes.copy_from_slice(&remaining_bytes[..bytes.len()]); - self.position += align_up(bytes.len(), WORD_SIZE) / WORD_SIZE; - Ok(()) - } -} - -/// A guest for the RISC0 VM. When running in the Risc0 environment, this struct -/// implements the `ZkvmGuest` trait in terms of Risc0's env::read and env::commit functions. -/// When running in any other environment, the struct uses interior mutability to emulate -/// the same functionality. -#[derive(Default)] -pub struct Risc0Guest { - #[cfg(not(target_os = "zkvm"))] - hints: std::sync::Mutex, - #[cfg(not(target_os = "zkvm"))] - commits: std::sync::Mutex>, -} - -impl Risc0Guest { - /// Constructs a new Risc0 Guest - pub fn new() -> Self { - Self::default() - } - - /// Constructs a new Risc0 Guest with the provided hints. - /// - /// This function is only available outside of Risc0's environment. - #[cfg(not(target_os = "zkvm"))] - pub fn with_hints(hints: Vec) -> Self { - Self { - hints: std::sync::Mutex::new(Hints::with_hints(hints)), - commits: Default::default(), - } - } -} - -#[cfg(not(target_os = "zkvm"))] -impl ZkvmGuest for Risc0Guest { - fn read_from_host(&self) -> T { - let mut hints = self.hints.lock().unwrap(); - let mut hints = hints.deref_mut(); - T::deserialize(&mut Deserializer::new(&mut hints)).unwrap() - } - - fn commit(&self, item: &T) { - self.commits.lock().unwrap().extend_from_slice( - &risc0_zkvm::serde::to_vec(item).expect("Serialization to vec is infallible"), - ); - } -} - -impl Zkvm for Risc0Guest { - type CodeCommitment = Risc0MethodId; - - type Error = anyhow::Error; - - fn verify<'a>( - _serialized_proof: &'a [u8], - _code_commitment: &Self::CodeCommitment, - ) -> Result<&'a [u8], Self::Error> { - // Implement this method once risc0 supports recursion: issue #633 - todo!("Implement once risc0 supports recursion: https://github.com/Sovereign-Labs/sovereign-sdk/issues/633") - } - - fn verify_and_extract_output< - Da: sov_rollup_interface::da::DaSpec, - Root: Serialize + DeserializeOwned, - >( - _serialized_proof: &[u8], - _code_commitment: &Self::CodeCommitment, - ) -> Result, Self::Error> { - todo!() - } -} diff --git a/crates/sovereign-sdk/adapters/risc0/src/guest/mod.rs b/crates/sovereign-sdk/adapters/risc0/src/guest/mod.rs new file mode 100644 index 000000000..caddcca4e --- /dev/null +++ b/crates/sovereign-sdk/adapters/risc0/src/guest/mod.rs @@ -0,0 +1,49 @@ +//! This module implements the `ZkvmGuest` trait for the RISC0 VM. +//! However the implementation is different +//! for host(native) and guest(zkvm) part. +//! The host implementation is used for tests only and brings no real value. + +use serde::de::DeserializeOwned; +use serde::Serialize; +use sov_rollup_interface::zk::Zkvm; + +use crate::Risc0MethodId; + +// Here goes the host/guest implementation: + +#[cfg(not(target_os = "zkvm"))] +mod native; +#[cfg(target_os = "zkvm")] +mod zkvm; + +#[cfg(not(target_os = "zkvm"))] +pub use native::Risc0Guest; +#[cfg(target_os = "zkvm")] +pub use zkvm::Risc0Guest; + +// Here goes the common implementation: + +// This is a dummy impl because T: ZkvmGuest where T: Zkvm. +impl Zkvm for Risc0Guest { + type CodeCommitment = Risc0MethodId; + + type Error = anyhow::Error; + + fn verify<'a>( + _serialized_proof: &'a [u8], + _code_commitment: &Self::CodeCommitment, + ) -> Result<&'a [u8], Self::Error> { + // Implement this method once risc0 supports recursion: issue #633 + todo!("Implement once risc0 supports recursion: https://github.com/Sovereign-Labs/sovereign-sdk/issues/633") + } + + fn verify_and_extract_output< + Da: sov_rollup_interface::da::DaSpec, + Root: Serialize + DeserializeOwned, + >( + _serialized_proof: &[u8], + _code_commitment: &Self::CodeCommitment, + ) -> Result, Self::Error> { + todo!() + } +} diff --git a/crates/sovereign-sdk/adapters/risc0/src/guest/native.rs b/crates/sovereign-sdk/adapters/risc0/src/guest/native.rs new file mode 100644 index 000000000..822f1e503 --- /dev/null +++ b/crates/sovereign-sdk/adapters/risc0/src/guest/native.rs @@ -0,0 +1,70 @@ +//! This module implements the `ZkvmGuest` trait for the RISC0 VM. + +use borsh::{BorshDeserialize, BorshSerialize}; +use sov_rollup_interface::zk::ZkvmGuest; + +#[derive(Default)] +struct Hints { + values: Vec, + position: usize, +} + +impl Hints { + pub fn with_hints(hints: Vec) -> Self { + Hints { + values: hints, + position: 0, + } + } +} + +/// A guest for the RISC0 VM. Implements the `ZkvmGuest` trait +/// using interior mutability to test the functionality. +#[derive(Default)] +pub struct Risc0Guest { + hints: std::sync::Mutex, + // commits: std::sync::Mutex>, +} + +impl Risc0Guest { + /// Constructs a new Risc0 Guest + pub fn new() -> Self { + Self::default() + } + + /// Constructs a new Risc0 Guest with the provided hints. + pub fn with_hints(hints: Vec) -> Self { + Self { + hints: std::sync::Mutex::new(Hints::with_hints(hints)), + // commits: Default::default(), + } + } +} + +impl ZkvmGuest for Risc0Guest { + fn read_from_host(&self) -> T { + let mut hints = self.hints.lock().unwrap(); + let hints = &mut *hints; + let pos = &mut hints.position; + let env = &hints.values; + // read len(u64) in LE + let len_buf = &env[*pos..*pos + 2]; + let len_bytes = bytemuck::cast_slice(len_buf); + let len_bytes: [u8; 8] = len_bytes.try_into().expect("Exactly 4 bytes"); + let len = u64::from_le_bytes(len_bytes) as usize; + *pos += 2; + // read buf + let buf = &env[*pos..*pos + len]; + let buf: &[u8] = bytemuck::cast_slice(buf); + *pos += len; + // deserialize + BorshDeserialize::deserialize(&mut &*buf).unwrap() + } + + fn commit(&self, _item: &T) { + unimplemented!("commitment never used in a test code") + // self.commits.lock().unwrap().extend_from_slice( + // &risc0_zkvm::serde::to_vec(item).expect("Serialization to vec is infallible"), + // ); + } +} diff --git a/crates/sovereign-sdk/adapters/risc0/src/guest/zkvm.rs b/crates/sovereign-sdk/adapters/risc0/src/guest/zkvm.rs new file mode 100644 index 000000000..cd718d200 --- /dev/null +++ b/crates/sovereign-sdk/adapters/risc0/src/guest/zkvm.rs @@ -0,0 +1,39 @@ +//! This module implements the `ZkvmGuest` trait for the RISC0 VM. +use borsh::{BorshDeserialize, BorshSerialize}; +use risc0_zkvm::guest::env; +use risc0_zkvm::guest::env::Write; +use sov_rollup_interface::zk::ZkvmGuest; + +/// A guest for the RISC0 VM. Implements the `ZkvmGuest` trait +/// in terms of Risc0's env::read and env::commit functions. +#[derive(Default)] +pub struct Risc0Guest {} + +impl Risc0Guest { + /// Constructs a new Risc0 Guest + pub fn new() -> Self { + Self::default() + } +} + +impl ZkvmGuest for Risc0Guest { + fn read_from_host(&self) -> T { + // read len(u64) in LE + let mut len_buf = [0u8; 8]; + env::read_slice(&mut len_buf); + let len = u64::from_le_bytes(len_buf); + // read buf + let mut buf: Vec = vec![0; len as usize]; + env::read_slice(&mut buf); + let slice: &[u8] = bytemuck::cast_slice(&buf); + // deserialize + BorshDeserialize::deserialize(&mut &*slice).expect("Failed to deserialize input from host") + } + + fn commit(&self, item: &T) { + // use risc0_zkvm::guest::env::Write as _; + let buf = borsh::to_vec(item).expect("Serialization to vec is infallible"); + let mut journal = env::journal(); + journal.write_slice(&buf); + } +} diff --git a/crates/sovereign-sdk/adapters/risc0/src/host.rs b/crates/sovereign-sdk/adapters/risc0/src/host.rs index 8c30bdfd5..2a0edbee4 100644 --- a/crates/sovereign-sdk/adapters/risc0/src/host.rs +++ b/crates/sovereign-sdk/adapters/risc0/src/host.rs @@ -1,5 +1,6 @@ //! This module implements the [`ZkvmHost`] trait for the RISC0 VM. +use borsh::{BorshDeserialize, BorshSerialize}; use risc0_zkvm::{ExecutorEnvBuilder, ExecutorImpl, InnerReceipt, Journal, Receipt, Session}; use serde::de::DeserializeOwned; use serde::Serialize; @@ -69,19 +70,21 @@ impl<'a> Risc0Host<'a> { impl<'a> ZkvmHost for Risc0Host<'a> { type Guest = Risc0Guest; - fn add_hint(&mut self, item: T) { - // We use the in-memory size of `item` as an indication of how much - // space to reserve. This is in no way guaranteed to be exact, but - // usually the in-memory size and serialized data size are quite close. - // - // Note: this is just an optimization to avoid frequent reallocations, - // it's not actually required. - self.env - .reserve(std::mem::size_of::() / std::mem::size_of::()); - - let mut serializer = risc0_zkvm::serde::Serializer::new(&mut self.env); - item.serialize(&mut serializer) - .expect("Risc0 hint serialization is infallible"); + fn add_hint(&mut self, item: T) { + let mut buf = borsh::to_vec(&item).expect("Risc0 hint serialization is infallible"); + // append [0..] alignment to cast &[u8] to &[u32] + let rem = buf.len() % 4; + if rem > 0 { + buf.extend(vec![0; 4 - rem]); + } + let buf: &[u32] = bytemuck::cast_slice(&buf); + // write len(u64) in LE + let len = buf.len() as u64; + let len_buf = &len.to_le_bytes()[..]; + let len_buf: &[u32] = bytemuck::cast_slice(len_buf); + self.env.extend_from_slice(len_buf); + // write buf + self.env.extend_from_slice(buf); } fn simulate_with_hints(&mut self) -> Self::Guest { @@ -100,19 +103,20 @@ impl<'a> ZkvmHost for Risc0Host<'a> { } } - fn extract_output( + fn extract_output( proof: &Proof, ) -> Result, Self::Error> { - match proof { + let journal = match proof { Proof::PublicInput(journal) => { let journal: Journal = bincode::deserialize(journal)?; - Ok(journal.decode()?) + journal } Proof::Full(data) => { let receipt: Receipt = bincode::deserialize(data)?; - Ok(receipt.journal.decode()?) + receipt.journal } - } + }; + Ok(BorshDeserialize::deserialize(&mut journal.bytes.as_ref())?) } } diff --git a/crates/sovereign-sdk/adapters/risc0/tests/native.rs b/crates/sovereign-sdk/adapters/risc0/tests/native.rs index 6075b9b56..2b902a83c 100644 --- a/crates/sovereign-sdk/adapters/risc0/tests/native.rs +++ b/crates/sovereign-sdk/adapters/risc0/tests/native.rs @@ -1,8 +1,8 @@ -use serde::{Deserialize, Serialize}; +use borsh::{BorshDeserialize, BorshSerialize}; use sov_risc0_adapter::host::Risc0Host; use sov_rollup_interface::zk::{ZkvmGuest, ZkvmHost}; -#[derive(Serialize, Deserialize, Debug, PartialEq)] +#[derive(BorshDeserialize, BorshSerialize, Debug, PartialEq)] struct TestStruct { ints: Vec, string: String, @@ -13,12 +13,12 @@ fn test_hints_roundtrip() { let mut host = Risc0Host::new(&[]); let hint_a = TestStruct { - ints: vec![1, 2, 3, 4, 5], + ints: vec![0, 1, 2, 3, 4], string: "hello".to_string(), }; let hint_b = TestStruct { - ints: vec![1, 2, 3, 4, 5], - string: "hello".to_string(), + ints: vec![5, 6, 7, 8, 9], + string: "world".to_string(), }; host.add_hint(&hint_a); diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs index 157ddfc21..456fd4535 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs @@ -25,7 +25,7 @@ //! Module Accessory State Table: //! - `(ModuleAddress, Key) -> Value` -use borsh::{maybestd, BorshDeserialize, BorshSerialize}; +use borsh::{BorshDeserialize, BorshSerialize}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use jmt::storage::{NibblePath, Node, NodeKey}; use jmt::Version; @@ -130,11 +130,8 @@ macro_rules! impl_borsh_value_codec { impl ::sov_schema_db::schema::ValueCodec<$table_name> for $value { fn encode_value( &self, - ) -> ::std::result::Result< - ::sov_rollup_interface::maybestd::vec::Vec, - ::sov_schema_db::CodecError, - > { - ::borsh::BorshSerialize::try_to_vec(self).map_err(Into::into) + ) -> ::std::result::Result<::std::vec::Vec, ::sov_schema_db::CodecError> { + ::borsh::to_vec(self).map_err(Into::into) } fn decode_value( @@ -161,8 +158,8 @@ macro_rules! define_table_with_default_codec { define_table_without_codec!($(#[$docs])+ ( $table_name ) $key => $value); impl ::sov_schema_db::schema::KeyEncoder<$table_name> for $key { - fn encode_key(&self) -> ::std::result::Result<::sov_rollup_interface::maybestd::vec::Vec, ::sov_schema_db::CodecError> { - ::borsh::BorshSerialize::try_to_vec(self).map_err(Into::into) + fn encode_key(&self) -> ::std::result::Result<::std::vec::Vec, ::sov_schema_db::CodecError> { + ::borsh::to_vec(self).map_err(Into::into) } } @@ -186,7 +183,7 @@ macro_rules! define_table_with_seek_key_codec { define_table_without_codec!($(#[$docs])+ ( $table_name ) $key => $value); impl ::sov_schema_db::schema::KeyEncoder<$table_name> for $key { - fn encode_key(&self) -> ::std::result::Result<::sov_rollup_interface::maybestd::vec::Vec, ::sov_schema_db::CodecError> { + fn encode_key(&self) -> ::std::result::Result<::std::vec::Vec, ::sov_schema_db::CodecError> { use ::anyhow::Context as _; use ::bincode::Options as _; @@ -212,7 +209,7 @@ macro_rules! define_table_with_seek_key_codec { } impl ::sov_schema_db::SeekKeyEncoder<$table_name> for $key { - fn encode_seek_key(&self) -> ::std::result::Result<::sov_rollup_interface::maybestd::vec::Vec, ::sov_schema_db::CodecError> { + fn encode_seek_key(&self) -> ::std::result::Result<::std::vec::Vec, ::sov_schema_db::CodecError> { >::encode_key(self) } } @@ -328,7 +325,7 @@ impl KeyEncoder for NodeKey { Vec::with_capacity(8 + 4 + 4 + ((self.nibble_path().num_nibbles() + 1) / 2)); let version = self.version().to_be_bytes(); output.extend_from_slice(&version); - self.nibble_path().serialize(&mut output)?; + BorshSerialize::serialize(self.nibble_path(), &mut output)?; Ok(output) } } @@ -350,11 +347,11 @@ impl KeyDecoder for NodeKey { impl ValueCodec for Node { fn encode_value(&self) -> sov_schema_db::schema::Result> { - self.try_to_vec().map_err(CodecError::from) + borsh::to_vec(self).map_err(CodecError::from) } fn decode_value(data: &[u8]) -> sov_schema_db::schema::Result { - Ok(Self::deserialize_reader(&mut &data[..])?) + Ok(BorshDeserialize::deserialize_reader(&mut &data[..])?) } } @@ -386,8 +383,8 @@ impl + PartialEq + core::fmt::Debug> SeekKeyEncoder fo impl KeyDecoder for (StateKey, Version) { fn decode_key(data: &[u8]) -> sov_schema_db::schema::Result { - let mut cursor = maybestd::io::Cursor::new(data); - let key = Vec::::deserialize_reader(&mut cursor)?; + let mut cursor = std::io::Cursor::new(data); + let key: Vec = BorshDeserialize::deserialize_reader(&mut cursor)?; let version = cursor.read_u64::()?; Ok((key, version)) } @@ -395,11 +392,11 @@ impl KeyDecoder for (StateKey, Version) { impl ValueCodec for JmtValue { fn encode_value(&self) -> sov_schema_db::schema::Result> { - self.try_to_vec().map_err(CodecError::from) + borsh::to_vec(self).map_err(CodecError::from) } fn decode_value(data: &[u8]) -> sov_schema_db::schema::Result { - Ok(Self::deserialize_reader(&mut &data[..])?) + Ok(BorshDeserialize::deserialize_reader(&mut &data[..])?) } } @@ -438,8 +435,8 @@ impl SeekKeyEncoder for (AccessoryKey, Version) { impl KeyDecoder for (AccessoryKey, Version) { fn decode_key(data: &[u8]) -> sov_schema_db::schema::Result { - let mut cursor = maybestd::io::Cursor::new(data); - let key = Vec::::deserialize_reader(&mut cursor)?; + let mut cursor = std::io::Cursor::new(data); + let key: Vec = BorshDeserialize::deserialize_reader(&mut cursor)?; let version = cursor.read_u64::()?; Ok((key, version)) } @@ -447,10 +444,10 @@ impl KeyDecoder for (AccessoryKey, Version) { impl ValueCodec for AccessoryStateValue { fn encode_value(&self) -> sov_schema_db::schema::Result> { - self.try_to_vec().map_err(CodecError::from) + borsh::to_vec(self).map_err(CodecError::from) } fn decode_value(data: &[u8]) -> sov_schema_db::schema::Result { - Ok(Self::deserialize_reader(&mut &data[..])?) + Ok(BorshDeserialize::deserialize_reader(&mut &data[..])?) } } diff --git a/crates/sovereign-sdk/full-node/sov-prover-storage-manager/benches/single_thread_progression.rs b/crates/sovereign-sdk/full-node/sov-prover-storage-manager/benches/single_thread_progression.rs index f750c70b4..f76753b26 100644 --- a/crates/sovereign-sdk/full-node/sov-prover-storage-manager/benches/single_thread_progression.rs +++ b/crates/sovereign-sdk/full-node/sov-prover-storage-manager/benches/single_thread_progression.rs @@ -110,9 +110,9 @@ fn setup_storage( ordered_writes, }; - let witness = ArrayWitness::default(); + let mut witness = ArrayWitness::default(); let (_, state_update, _) = storage - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage.commit(&state_update, &OrderedReadsAndWrites::default()); @@ -172,8 +172,8 @@ fn bench_random_read( |b, i| { b.iter(|| { let (storage, random_key) = i; - let witness = ArrayWitness::default(); - let result = black_box(storage.get(random_key, None, &witness)); + let mut witness = ArrayWitness::default(); + let result = black_box(storage.get(random_key, None, &mut witness)); assert!(result.is_some()); black_box(result); }) @@ -216,8 +216,8 @@ fn bench_not_found_read( |b, i| { b.iter(|| { let (storage, random_key) = i; - let witness = ArrayWitness::default(); - let result = black_box(storage.get(random_key, None, &witness)); + let mut witness = ArrayWitness::default(); + let result = black_box(storage.get(random_key, None, &mut witness)); assert!(result.is_none()); black_box(result); }) diff --git a/crates/sovereign-sdk/full-node/sov-prover-storage-manager/src/lib.rs b/crates/sovereign-sdk/full-node/sov-prover-storage-manager/src/lib.rs index c8aeafd63..b718543ed 100644 --- a/crates/sovereign-sdk/full-node/sov-prover-storage-manager/src/lib.rs +++ b/crates/sovereign-sdk/full-node/sov-prover-storage-manager/src/lib.rs @@ -913,14 +913,14 @@ mod tests { let block_c = MockBlockHeader::from_height(3); let storage_a = storage_manager.create_storage_on(&block_a).unwrap(); - let witness = ArrayWitness::default(); + let mut witness = ArrayWitness::default(); { let mut state_operations = OrderedReadsAndWrites::default(); state_operations.ordered_writes.push(write_op(1, 2)); let mut native_operations = OrderedReadsAndWrites::default(); native_operations.ordered_writes.push(write_op(30, 40)); let (_, state_update, _) = storage_a - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_a.commit(&state_update, &native_operations); } @@ -935,7 +935,7 @@ mod tests { let mut native_operations = OrderedReadsAndWrites::default(); native_operations.ordered_writes.push(write_op(50, 60)); let (_, state_update, _) = storage_b - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_b.commit(&state_update, &native_operations); } @@ -949,11 +949,11 @@ mod tests { assert_eq!( Some(value_from(2).into()), - storage_c.get(&key_from(1).into(), None, &witness) + storage_c.get(&key_from(1).into(), None, &mut witness) ); assert_eq!( Some(value_from(4).into()), - storage_c.get(&key_from(3).into(), None, &witness) + storage_c.get(&key_from(3).into(), None, &mut witness) ); assert_eq!( Some(value_from(40).into()), @@ -1087,7 +1087,7 @@ mod tests { // | G | aux | 2 | write(9) | // | L | state | 1 | write(10) | - let witness = ArrayWitness::default(); + let mut witness = ArrayWitness::default(); // A let storage_a = storage_manager.create_storage_on(&block_a).unwrap(); { @@ -1098,7 +1098,7 @@ mod tests { native_operations.ordered_writes.push(write_op(3, 40)); let (_, state_update, _) = storage_a - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_a.commit(&state_update, &native_operations); } @@ -1114,7 +1114,7 @@ mod tests { let mut native_operations = OrderedReadsAndWrites::default(); native_operations.ordered_writes.push(write_op(3, 50)); let (_, state_update, _) = storage_b - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_b.commit(&state_update, &native_operations); } @@ -1130,7 +1130,7 @@ mod tests { let mut native_operations = OrderedReadsAndWrites::default(); native_operations.ordered_writes.push(write_op(1, 60)); let (_, state_update, _) = storage_c - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_c.commit(&state_update, &native_operations); } @@ -1143,7 +1143,7 @@ mod tests { let mut state_operations = OrderedReadsAndWrites::default(); state_operations.ordered_writes.push(write_op(3, 6)); let (_, state_update, _) = storage_d - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_d.commit(&state_update, &OrderedReadsAndWrites::default()); } @@ -1160,7 +1160,7 @@ mod tests { native_operations.ordered_writes.push(delete_op(1)); native_operations.ordered_writes.push(write_op(3, 70)); let (_, state_update, _) = storage_f - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_f.commit(&state_update, &native_operations); } @@ -1175,7 +1175,7 @@ mod tests { let mut native_operations = OrderedReadsAndWrites::default(); native_operations.ordered_writes.push(write_op(2, 9)); let (_, state_update, _) = storage_g - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_g.commit(&state_update, &native_operations); } @@ -1188,7 +1188,7 @@ mod tests { let mut state_operations = OrderedReadsAndWrites::default(); state_operations.ordered_writes.push(write_op(1, 10)); let (_, state_update, _) = storage_l - .compute_state_update(state_operations, &witness) + .compute_state_update(state_operations, &mut witness) .unwrap(); storage_l.commit(&state_update, &OrderedReadsAndWrites::default()); } @@ -1232,16 +1232,16 @@ mod tests { let storage_h = storage_manager.create_storage_on(&block_h).unwrap(); let storage_k = storage_manager.create_storage_on(&block_k).unwrap(); - let assert_main_fork = || { - assert_eq!(None, storage_e.get(&key_from(1).into(), None, &witness)); - assert_eq!(None, storage_e.get(&key_from(2).into(), None, &witness)); + let assert_main_fork = |witness: &mut ArrayWitness| { + assert_eq!(None, storage_e.get(&key_from(1).into(), None, witness)); + assert_eq!(None, storage_e.get(&key_from(2).into(), None, witness)); assert_eq!( Some(value_from(6).into()), - storage_e.get(&key_from(3).into(), None, &witness) + storage_e.get(&key_from(3).into(), None, witness) ); assert_eq!( Some(value_from(5).into()), - storage_e.get(&key_from(4).into(), None, &witness) + storage_e.get(&key_from(4).into(), None, witness) ); assert_eq!( Some(value_from(60).into()), @@ -1254,17 +1254,17 @@ mod tests { ); }; // Storage M - let assert_storage_m = || { + let assert_storage_m = |witness: &mut ArrayWitness| { assert_eq!( Some(value_from(10).into()), - storage_m.get(&key_from(1).into(), None, &witness) + storage_m.get(&key_from(1).into(), None, witness) ); - assert_eq!(None, storage_m.get(&key_from(2).into(), None, &witness)); + assert_eq!(None, storage_m.get(&key_from(2).into(), None, witness)); assert_eq!( Some(value_from(2).into()), - storage_m.get(&key_from(3).into(), None, &witness) + storage_m.get(&key_from(3).into(), None, witness) ); - assert_eq!(None, storage_m.get(&key_from(4).into(), None, &witness)); + assert_eq!(None, storage_m.get(&key_from(4).into(), None, witness)); assert_eq!(None, storage_m.get_accessory(&key_from(1).into(), None)); assert_eq!(None, storage_m.get_accessory(&key_from(2).into(), None)); assert_eq!( @@ -1273,17 +1273,17 @@ mod tests { ); }; // Storage H - let assert_storage_h = || { + let assert_storage_h = |witness: &mut ArrayWitness| { assert_eq!( Some(value_from(8).into()), - storage_h.get(&key_from(1).into(), None, &witness) + storage_h.get(&key_from(1).into(), None, witness) ); - assert_eq!(None, storage_h.get(&key_from(2).into(), None, &witness)); + assert_eq!(None, storage_h.get(&key_from(2).into(), None, witness)); assert_eq!( Some(value_from(2).into()), - storage_h.get(&key_from(3).into(), None, &witness) + storage_h.get(&key_from(3).into(), None, witness) ); - assert_eq!(None, storage_h.get(&key_from(4).into(), None, &witness)); + assert_eq!(None, storage_h.get(&key_from(4).into(), None, witness)); assert_eq!(None, storage_h.get_accessory(&key_from(1).into(), None)); assert_eq!( Some(value_from(9).into()), @@ -1294,17 +1294,17 @@ mod tests { storage_h.get_accessory(&key_from(3).into(), None) ); }; - assert_main_fork(); - assert_storage_m(); - assert_storage_h(); + assert_main_fork(&mut witness); + assert_storage_m(&mut witness); + assert_storage_h(&mut witness); // Storage K assert_eq!( Some(value_from(7).into()), - storage_k.get(&key_from(1).into(), None, &witness) + storage_k.get(&key_from(1).into(), None, &mut witness) ); - assert_eq!(None, storage_k.get(&key_from(2).into(), None, &witness)); - assert_eq!(None, storage_k.get(&key_from(3).into(), None, &witness)); - assert_eq!(None, storage_k.get(&key_from(4).into(), None, &witness)); + assert_eq!(None, storage_k.get(&key_from(2).into(), None, &mut witness)); + assert_eq!(None, storage_k.get(&key_from(3).into(), None, &mut witness)); + assert_eq!(None, storage_k.get(&key_from(4).into(), None, &mut witness)); assert_eq!(None, storage_k.get_accessory(&key_from(1).into(), None)); assert_eq!(None, storage_k.get_accessory(&key_from(2).into(), None)); assert_eq!( @@ -1317,20 +1317,20 @@ mod tests { .unwrap(); storage_manager.finalize(&block_a).unwrap(); validate_internal_consistency(&storage_manager); - assert_main_fork(); - assert_storage_m(); - assert_storage_h(); + assert_main_fork(&mut witness); + assert_storage_m(&mut witness); + assert_storage_h(&mut witness); // Finalizing the rest storage_manager.finalize(&block_b).unwrap(); validate_internal_consistency(&storage_manager); - assert_main_fork(); + assert_main_fork(&mut witness); storage_manager.finalize(&block_c).unwrap(); validate_internal_consistency(&storage_manager); - assert_main_fork(); + assert_main_fork(&mut witness); storage_manager.finalize(&block_d).unwrap(); validate_internal_consistency(&storage_manager); - assert_main_fork(); + assert_main_fork(&mut witness); storage_manager .save_change_set(&block_e, storage_e) .unwrap(); @@ -1351,7 +1351,7 @@ mod tests { .unwrap(); assert_eq!( Some(value_from(6).into()), - storage_last.get(&key_from(3).into(), None, &witness) + storage_last.get(&key_from(3).into(), None, &mut witness) ); assert_eq!( Some(value_from(50).into()), diff --git a/crates/sovereign-sdk/full-node/sov-sequencer/src/batch_builder.rs b/crates/sovereign-sdk/full-node/sov-sequencer/src/batch_builder.rs index 0f89d2c04..2150c037b 100644 --- a/crates/sovereign-sdk/full-node/sov-sequencer/src/batch_builder.rs +++ b/crates/sovereign-sdk/full-node/sov-sequencer/src/batch_builder.rs @@ -178,7 +178,7 @@ where #[cfg(test)] mod tests { - use borsh::BorshSerialize; + use borsh::{BorshDeserialize, BorshSerialize}; use rand::Rng; use sov_modules_api::default_context::DefaultContext; use sov_modules_api::default_signature::private_key::DefaultPrivateKey; @@ -200,7 +200,7 @@ mod tests { type C = DefaultContext; #[derive(Genesis, DispatchCall, MessageCodec, DefaultRuntime)] - #[serialization(borsh::BorshDeserialize, borsh::BorshSerialize)] + #[serialization(BorshDeserialize, BorshSerialize)] struct TestRuntime { value_setter: sov_value_setter::ValueSetter, } @@ -218,9 +218,9 @@ mod tests { let chain_id = 0; let nonce = 1; - Transaction::::new_signed_tx(private_key, msg, chain_id, nonce) - .try_to_vec() - .unwrap() + let transaction = + Transaction::::new_signed_tx(private_key, msg, chain_id, nonce); + borsh::to_vec(&transaction).unwrap() } fn generate_random_bytes() -> Vec { @@ -236,9 +236,9 @@ mod tests { let chain_id = 0; let nonce = 1; - Transaction::::new_signed_tx(private_key, msg, chain_id, nonce) - .try_to_vec() - .unwrap() + let transaction = + Transaction::::new_signed_tx(private_key, msg, chain_id, nonce); + borsh::to_vec(&transaction).unwrap() } fn create_batch_builder( @@ -277,8 +277,8 @@ mod tests { }; let config = GenesisConfig::::new(value_setter_config); runtime.genesis(&config, &mut working_set).unwrap(); - let (log, witness) = working_set.checkpoint().freeze(); - storage.validate_and_commit(log, &witness).unwrap(); + let (log, mut witness) = working_set.checkpoint().freeze(); + storage.validate_and_commit(log, &mut witness).unwrap(); } mod accept_tx { diff --git a/crates/sovereign-sdk/full-node/sov-sequencer/src/utils.rs b/crates/sovereign-sdk/full-node/sov-sequencer/src/utils.rs index befa37859..2a1c9934d 100644 --- a/crates/sovereign-sdk/full-node/sov-sequencer/src/utils.rs +++ b/crates/sovereign-sdk/full-node/sov-sequencer/src/utils.rs @@ -27,7 +27,7 @@ impl SimpleClient { /// Sends a transaction to the sequencer for immediate publication. pub async fn send_transaction(&self, tx: Tx) -> Result<(), anyhow::Error> { - let batch = vec![tx.try_to_vec()?]; + let batch = vec![borsh::to_vec(&tx)?]; let response: String = self .http_client @@ -45,7 +45,7 @@ impl SimpleClient { ) -> Result<(), anyhow::Error> { let serialized_txs: Vec> = txs .into_iter() - .map(|tx| tx.try_to_vec()) + .map(|tx| borsh::to_vec(&tx)) .collect::>()?; match chunk_size { diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/src/prover_service/parallel/mod.rs b/crates/sovereign-sdk/full-node/sov-stf-runner/src/prover_service/parallel/mod.rs index e68b55ce0..1483f793d 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/src/prover_service/parallel/mod.rs +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/src/prover_service/parallel/mod.rs @@ -2,7 +2,7 @@ mod prover; use std::sync::Arc; use async_trait::async_trait; -use borsh::BorshSerialize as _; +use borsh::{BorshDeserialize, BorshSerialize}; use prover::Prover; use serde::de::DeserializeOwned; use serde::Serialize; @@ -35,8 +35,17 @@ where impl ParallelProverService where - StateRoot: Serialize + DeserializeOwned + Clone + AsRef<[u8]> + Send + Sync + 'static, - Witness: Serialize + DeserializeOwned + Send + Sync + 'static, + StateRoot: BorshSerialize + + BorshDeserialize + + Serialize + + DeserializeOwned + + Clone + + AsRef<[u8]> + + Send + + Sync + + 'static, + Witness: + BorshSerialize + BorshDeserialize + Serialize + DeserializeOwned + Send + Sync + 'static, Da: DaService, Vm: ZkvmHost, V: StateTransitionFunction + Send + Sync, @@ -113,8 +122,17 @@ where impl ProverService for ParallelProverService where - StateRoot: Serialize + DeserializeOwned + Clone + AsRef<[u8]> + Send + Sync + 'static, - Witness: Serialize + DeserializeOwned + Send + Sync + 'static, + StateRoot: BorshSerialize + + BorshDeserialize + + Serialize + + DeserializeOwned + + Clone + + AsRef<[u8]> + + Send + + Sync + + 'static, + Witness: + BorshSerialize + BorshDeserialize + Serialize + DeserializeOwned + Send + Sync + 'static, Da: DaService, Vm: ZkvmHost + 'static, V: StateTransitionFunction + Send + Sync + 'static, @@ -169,7 +187,9 @@ where let tx_id = da_service .send_transaction( - da_data.try_to_vec().expect("Should serialize").as_slice(), + borsh::to_vec(&da_data) + .expect("Should serialize") + .as_slice(), ) .await .map_err(|e| anyhow::anyhow!(e))?; diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/src/prover_service/parallel/prover.rs b/crates/sovereign-sdk/full-node/sov-stf-runner/src/prover_service/parallel/prover.rs index f85e2e4c2..511147849 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/src/prover_service/parallel/prover.rs +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/src/prover_service/parallel/prover.rs @@ -4,6 +4,7 @@ use std::ops::Deref; use std::sync::{Arc, RwLock}; use anyhow::anyhow; +use borsh::{BorshDeserialize, BorshSerialize}; use serde::de::DeserializeOwned; use serde::Serialize; use sov_rollup_interface::da::{BlockHeaderTrait, DaSpec}; @@ -84,8 +85,17 @@ pub(crate) struct Prover { impl Prover where Da: DaService, - StateRoot: Serialize + DeserializeOwned + Clone + AsRef<[u8]> + Send + Sync + 'static, - Witness: Serialize + DeserializeOwned + Send + Sync + 'static, + StateRoot: BorshSerialize + + BorshDeserialize + + Serialize + + DeserializeOwned + + Clone + + AsRef<[u8]> + + Send + + Sync + + 'static, + Witness: + BorshSerialize + BorshDeserialize + Serialize + DeserializeOwned + Send + Sync + 'static, { pub(crate) fn new(num_threads: usize) -> anyhow::Result { Ok(Self { diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/src/runner.rs b/crates/sovereign-sdk/full-node/sov-stf-runner/src/runner.rs index e75fcfdd4..a28d1344b 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/src/runner.rs +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/src/runner.rs @@ -6,7 +6,6 @@ use anyhow::{anyhow, bail}; use backoff::future::retry as retry_backoff; use backoff::ExponentialBackoffBuilder; use borsh::de::BorshDeserialize; -use borsh::BorshSerialize as _; use hyper::Method; use jsonrpsee::core::client::Error as JsonrpseeError; use jsonrpsee::RpcModule; @@ -625,7 +624,7 @@ where da_slot_hash: transition_data.da_slot_hash.into(), sequencer_public_key: transition_data.sequencer_public_key, sequencer_da_public_key: transition_data.sequencer_da_public_key, - validity_condition: transition_data.validity_condition.try_to_vec().unwrap(), + validity_condition: borsh::to_vec(&transition_data.validity_condition).unwrap(), }; match pg_client.as_ref() { @@ -874,9 +873,7 @@ where da_slot_hash: state_transition.da_slot_hash.clone().into(), sequencer_public_key: state_transition.sequencer_public_key, sequencer_da_public_key: state_transition.sequencer_da_public_key, - validity_condition: state_transition - .validity_condition - .try_to_vec() + validity_condition: borsh::to_vec(&state_transition.validity_condition) .unwrap(), }; diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/tests/hash_stf.rs b/crates/sovereign-sdk/full-node/sov-stf-runner/tests/hash_stf.rs index 259914737..6548eec9d 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/tests/hash_stf.rs +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/tests/hash_stf.rs @@ -37,7 +37,7 @@ impl HashStf { fn save_from_hasher( hasher: sha2::Sha256, storage: ProverStorage, - witness: &ArrayWitness, + witness: &mut ArrayWitness, ) -> ([u8; 32], ProverStorage) { let result = hasher.finalize(); @@ -149,14 +149,14 @@ impl StateTransitionFunction::save_from_hasher(hasher, genesis_state, &ArrayWitness::default()) + HashStf::::save_from_hasher(hasher, genesis_state, &mut ArrayWitness::default()) } fn apply_slot<'a, I>( &self, pre_state_root: &Self::StateRoot, storage: Self::PreState, - witness: Self::Witness, + mut witness: Self::Witness, slot_header: &Da::BlockHeader, _validity_condition: &Da::ValidityCondition, blobs: I, @@ -177,7 +177,7 @@ impl StateTransitionFunction::hash_key(); - let existing_cache = storage.get(&hash_key, None, &witness).unwrap(); + let existing_cache = storage.get(&hash_key, None, &mut witness).unwrap(); tracing::debug!( "HashStf provided_state_root={:?}, saved={:?}", pre_state_root, @@ -190,7 +190,8 @@ impl StateTransitionFunction::save_from_hasher(hasher, storage, &witness); + let (state_root, storage) = + HashStf::::save_from_hasher(hasher, storage, &mut witness); SlotResult { state_root, diff --git a/crates/sovereign-sdk/fuzz/Cargo.lock b/crates/sovereign-sdk/fuzz/Cargo.lock index 22c8aa1c3..d275e6c5d 100644 --- a/crates/sovereign-sdk/fuzz/Cargo.lock +++ b/crates/sovereign-sdk/fuzz/Cargo.lock @@ -281,48 +281,27 @@ dependencies = [ [[package]] name = "borsh" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "bytes", - "hashbrown 0.13.2", + "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2 1.0.84", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2 1.0.84", - "quote 1.0.36", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ + "once_cell", + "proc-macro-crate", "proc-macro2 1.0.84", "quote 1.0.36", - "syn 1.0.109", + "syn 2.0.66", + "syn_derive", ] [[package]] @@ -374,6 +353,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "clang-sys" version = "1.8.1" @@ -802,6 +787,9 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] [[package]] name = "heck" @@ -985,8 +973,8 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jmt" -version = "0.9.0" -source = "git+https://github.com/penumbra-zone/jmt.git?rev=1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6#1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6" +version = "0.10.0" +source = "git+https://github.com/penumbra-zone/jmt.git?rev=fd1c8ef#fd1c8ef99913663eb801576a9b13a31523861d87" dependencies = [ "anyhow", "borsh", @@ -1077,7 +1065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d0bb047e79a143b32ea03974a6bf59b62c2a4c5f5d42a381c907a8bbb3f75c0" dependencies = [ "heck 0.4.1", - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2 1.0.84", "quote 1.0.36", "syn 2.0.66", @@ -1430,20 +1418,34 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "0.1.5" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml", + "toml_edit", ] [[package]] -name = "proc-macro-crate" -version = "3.1.0" +name = "proc-macro-error" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "toml_edit", + "proc-macro-error-attr", + "proc-macro2 1.0.84", + "quote 1.0.36", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2 1.0.84", + "quote 1.0.36", + "version_check", ] [[package]] @@ -2079,6 +2081,7 @@ dependencies = [ "borsh", "derive_more", "digest 0.10.7", + "hashbrown 0.14.5", "hex", "jmt", "proptest", @@ -2243,6 +2246,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.84", + "quote 1.0.36", + "syn 2.0.66", +] + [[package]] name = "tempfile" version = "3.10.1" @@ -2356,15 +2371,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml_datetime" version = "0.6.6" diff --git a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/tests/test.rs b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/tests/test.rs index bc545912a..36f7c57e8 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/tests/test.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/tests/test.rs @@ -33,8 +33,10 @@ fn test_accessory_value_setter() { ) .unwrap(); - let (reads_writes, witness) = working_set_for_state.checkpoint().freeze(); - let state_root_hash = storage.validate_and_commit(reads_writes, &witness).unwrap(); + let (reads_writes, mut witness) = working_set_for_state.checkpoint().freeze(); + let state_root_hash = storage + .validate_and_commit(reads_writes, &mut witness) + .unwrap(); module .call( @@ -45,10 +47,10 @@ fn test_accessory_value_setter() { .unwrap(); let mut checkpoint = working_set_for_accessory.checkpoint(); - let (reads_writes, witness) = checkpoint.freeze(); + let (reads_writes, mut witness) = checkpoint.freeze(); let accessory_writes = checkpoint.freeze_non_provable(); let state_root_hash_2 = storage - .validate_and_commit_with_accessory_update(reads_writes, &witness, &accessory_writes) + .validate_and_commit_with_accessory_update(reads_writes, &mut witness, &accessory_writes) .unwrap(); assert_eq!( diff --git a/crates/sovereign-sdk/module-system/module-implementations/integration-tests/src/nested_modules/tests.rs b/crates/sovereign-sdk/module-system/module-implementations/integration-tests/src/nested_modules/tests.rs index 6c83f13f8..620ed29ac 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/integration-tests/src/nested_modules/tests.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/integration-tests/src/nested_modules/tests.rs @@ -28,9 +28,9 @@ fn nested_module_call_test() { ] ); - let (log, witness) = working_set.checkpoint().freeze(); + let (log, mut witness) = working_set.checkpoint().freeze(); prover_storage - .validate_and_commit(log, &witness) + .validate_and_commit(log, &mut witness) .expect("State update is valid"); // Test the `zk` execution. diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-bank/src/call.rs b/crates/sovereign-sdk/module-system/module-implementations/sov-bank/src/call.rs index 1a50e6f92..dd160d48c 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-bank/src/call.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-bank/src/call.rs @@ -1,4 +1,5 @@ use anyhow::{bail, Context, Result}; +use borsh::{BorshDeserialize, BorshSerialize}; #[cfg(feature = "native")] use sov_modules_api::macros::CliWalletArg; use sov_modules_api::{CallResponse, StateMapAccessor, WorkingSet}; @@ -17,7 +18,7 @@ use crate::{Amount, Bank, Coins, Token}; derive(serde::Serialize), derive(serde::Deserialize) )] -#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, PartialEq, Clone)] +#[derive(BorshDeserialize, BorshSerialize, Debug, PartialEq, Clone)] pub enum CallMessage { /// Creates a new token with the specified name and initial balance. CreateToken { diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-bank/tests/archival_query_test.rs b/crates/sovereign-sdk/module-system/module-implementations/sov-bank/tests/archival_query_test.rs index b06874d73..e19d47a56 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-bank/tests/archival_query_test.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-bank/tests/archival_query_test.rs @@ -277,10 +277,10 @@ fn commit( // Save checkpoint let mut checkpoint = working_set.checkpoint(); - let (cache_log, witness) = checkpoint.freeze(); + let (cache_log, mut witness) = checkpoint.freeze(); let (_, authenticated_node_batch, _) = storage - .compute_state_update(cache_log, &witness) + .compute_state_update(cache_log, &mut witness) .expect("jellyfish merkle tree update must succeed"); let working_set = checkpoint.to_revertable(); diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-prover-incentives/src/tests.rs b/crates/sovereign-sdk/module-system/module-implementations/sov-prover-incentives/src/tests.rs index 64c4c777f..7d59d08ea 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-prover-incentives/src/tests.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-prover-incentives/src/tests.rs @@ -96,7 +96,7 @@ fn test_burn_on_invalid_proof() { let proof = MockProof { program_id: MOCK_CODE_COMMITMENT, is_valid: false, - log: &[], + log: vec![], }; module .process_proof(proof.encode_to_vec().as_ref(), &context, &mut working_set) @@ -132,7 +132,7 @@ fn test_valid_proof() { let proof = MockProof { program_id: MOCK_CODE_COMMITMENT, is_valid: true, - log: &[], + log: vec![], }; module .process_proof(proof.encode_to_vec().as_ref(), &context, &mut working_set) @@ -224,7 +224,7 @@ fn test_prover_not_bonded() { let proof = MockProof { program_id: MOCK_CODE_COMMITMENT, is_valid: true, - log: &[], + log: vec![], }; // Assert that processing a valid proof fails assert!(module diff --git a/crates/sovereign-sdk/module-system/sov-cli/src/wallet_state.rs b/crates/sovereign-sdk/module-system/sov-cli/src/wallet_state.rs index 378da4577..153e8e270 100644 --- a/crates/sovereign-sdk/module-system/sov-cli/src/wallet_state.rs +++ b/crates/sovereign-sdk/module-system/sov-cli/src/wallet_state.rs @@ -253,9 +253,7 @@ mod pubkey_hex { where S: Serializer, { - let bytes = data - .try_to_vec() - .expect("serialization to vec is infallible"); + let bytes = borsh::to_vec(data).expect("serialization to vec is infallible"); let formatted_string = format!("0x{}", bytes.encode_hex::()); serializer.serialize_str(&formatted_string) } @@ -284,7 +282,7 @@ mod pubkey_hex { { let data = data.trim_start_matches("0x"); let bytes: Vec = FromHex::from_hex(data).map_err(Error::custom)?; - C::try_from_slice(&bytes).map_err(Error::custom) + BorshDeserialize::try_from_slice(&bytes).map_err(Error::custom) } fn visit_borrowed_str(self, data: &'de str) -> Result @@ -293,7 +291,7 @@ mod pubkey_hex { { let data = data.trim_start_matches("0x"); let bytes: Vec = FromHex::from_hex(data).map_err(Error::custom)?; - C::try_from_slice(&bytes).map_err(Error::custom) + BorshDeserialize::try_from_slice(&bytes).map_err(Error::custom) } } diff --git a/crates/sovereign-sdk/module-system/sov-cli/src/workflows/rpc.rs b/crates/sovereign-sdk/module-system/sov-cli/src/workflows/rpc.rs index 0ddf7fccb..d4afedb2a 100644 --- a/crates/sovereign-sdk/module-system/sov-cli/src/workflows/rpc.rs +++ b/crates/sovereign-sdk/module-system/sov-cli/src/workflows/rpc.rs @@ -153,14 +153,13 @@ impl R .into_iter() .enumerate() .map(|(offset, tx)| { - Transaction::::new_signed_tx( + let transaction = Transaction::::new_signed_tx( &private_key, - tx.try_to_vec().unwrap(), + borsh::to_vec(&tx).unwrap(), tx.chain_id, nonce + offset as u64, - ) - .try_to_vec() - .unwrap() + ); + borsh::to_vec(&transaction).unwrap() }) .collect::>(); diff --git a/crates/sovereign-sdk/module-system/sov-modules-api/src/containers/mod.rs b/crates/sovereign-sdk/module-system/sov-modules-api/src/containers/mod.rs index 90b0e64ef..3abf29f83 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-api/src/containers/mod.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-api/src/containers/mod.rs @@ -85,13 +85,13 @@ mod test { WorkingSet::new(prover_storage.clone()); working_set.set(&test.key, test.value.clone()); - let (cache, witness) = working_set.checkpoint().freeze(); + let (cache, mut witness) = working_set.checkpoint().freeze(); prover_storage - .validate_and_commit(cache, &witness) + .validate_and_commit(cache, &mut witness) .expect("storage is valid"); assert_eq!( test.value, - prover_storage.get(&test.key, None, &witness).unwrap() + prover_storage.get(&test.key, None, &mut witness).unwrap() ); } } @@ -111,7 +111,7 @@ mod test { assert_eq!( test.value, storage - .get(&test.key, Some(test.version), &Default::default()) + .get(&test.key, Some(test.version), &mut Default::default()) .unwrap() ); } @@ -145,9 +145,9 @@ mod test { assert!(prover_storage.is_empty()); let mut storage: WorkingSet = WorkingSet::new(prover_storage.clone()); storage.set(&key, value.clone()); - let (cache, witness) = storage.checkpoint().freeze(); + let (cache, mut witness) = storage.checkpoint().freeze(); prover_storage - .validate_and_commit(cache, &witness) + .validate_and_commit(cache, &mut witness) .expect("storage is valid"); storage_manager .save_change_set(&header, prover_storage) @@ -164,7 +164,9 @@ mod test { assert!(!prover_storage.is_empty()); assert_eq!( value, - prover_storage.get(&key, None, &Default::default()).unwrap() + prover_storage + .get(&key, None, &mut Default::default()) + .unwrap() ); } } diff --git a/crates/sovereign-sdk/module-system/sov-modules-api/src/default_context.rs b/crates/sovereign-sdk/module-system/sov-modules-api/src/default_context.rs index a8e29eecf..38b0f717a 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-api/src/default_context.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-api/src/default_context.rs @@ -1,5 +1,6 @@ use std::fmt::Debug; +use borsh::{BorshDeserialize, BorshSerialize}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use sha2::Digest; @@ -15,7 +16,7 @@ use crate::default_signature::{DefaultPublicKey, DefaultSignature}; #[cfg(feature = "native")] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, Serialize, Deserialize)] pub struct DefaultContext { pub sender: Address, pub sequencer: Address, @@ -57,7 +58,7 @@ impl Context for DefaultContext { } } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ZkDefaultContext { pub sender: Address, diff --git a/crates/sovereign-sdk/module-system/sov-modules-api/src/hooks.rs b/crates/sovereign-sdk/module-system/sov-modules-api/src/hooks.rs index 766c064f5..593be47de 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-api/src/hooks.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-api/src/hooks.rs @@ -189,7 +189,7 @@ impl HookSoftConfirmationInfo { /// Borsh serialized data pub fn full_data(&mut self) -> Vec { - self.try_to_vec().unwrap() + borsh::to_vec(self).unwrap() } pub fn deposit_data(&self) -> Vec> { diff --git a/crates/sovereign-sdk/module-system/sov-modules-api/src/tests.rs b/crates/sovereign-sdk/module-system/sov-modules-api/src/tests.rs index be7d0bb8d..5d72ffab5 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-api/src/tests.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-api/src/tests.rs @@ -1,4 +1,4 @@ -use borsh::{BorshDeserialize, BorshSerialize}; +use borsh::BorshDeserialize; use sov_modules_core::{Address, PrivateKey, Signature}; use crate::default_context::DefaultContext; @@ -19,9 +19,10 @@ fn test_account_bech32m_display() { #[test] fn test_pub_key_serialization() { let pub_key = DefaultPrivateKey::generate().pub_key(); - let serialized_pub_key = pub_key.try_to_vec().unwrap(); + let serialized_pub_key = borsh::to_vec(&pub_key).unwrap(); - let deserialized_pub_key = DefaultPublicKey::try_from_slice(&serialized_pub_key).unwrap(); + let deserialized_pub_key: DefaultPublicKey = + BorshDeserialize::try_from_slice(&serialized_pub_key).unwrap(); assert_eq!(pub_key, deserialized_pub_key) } @@ -31,8 +32,9 @@ fn test_signature_serialization() { let priv_key = DefaultPrivateKey::generate(); let sig = priv_key.sign(&msg); - let serialized_sig = sig.try_to_vec().unwrap(); - let deserialized_sig = DefaultSignature::try_from_slice(&serialized_sig).unwrap(); + let serialized_sig = borsh::to_vec(&sig).unwrap(); + let deserialized_sig: DefaultSignature = + BorshDeserialize::try_from_slice(&serialized_sig).unwrap(); assert_eq!(sig, deserialized_sig); let pub_key = priv_key.pub_key(); diff --git a/crates/sovereign-sdk/module-system/sov-modules-api/tests/state_tests.rs b/crates/sovereign-sdk/module-system/sov-modules-api/tests/state_tests.rs index 96a612b36..a7d95a815 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-api/tests/state_tests.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-api/tests/state_tests.rs @@ -18,9 +18,9 @@ impl Operation { match self { Operation::Merge => working_set.checkpoint(), Operation::Finalize => { - let (cache_log, witness) = working_set.checkpoint().freeze(); + let (cache_log, mut witness) = working_set.checkpoint().freeze(); - db.validate_and_commit(cache_log, &witness) + db.validate_and_commit(cache_log, &mut witness) .expect("JMT update is valid"); StateCheckpoint::new(db) @@ -177,10 +177,10 @@ fn test_witness_round_trip() { state_value.set(&11, &mut working_set); let _ = state_value.get(&mut working_set); state_value.set(&22, &mut working_set); - let (cache_log, witness) = working_set.checkpoint().freeze(); + let (cache_log, mut witness) = working_set.checkpoint().freeze(); let _ = storage - .validate_and_commit(cache_log, &witness) + .validate_and_commit(cache_log, &mut witness) .expect("Native jmt validation should succeed"); witness }; @@ -192,10 +192,10 @@ fn test_witness_round_trip() { state_value.set(&11, &mut working_set); let _ = state_value.get(&mut working_set); state_value.set(&22, &mut working_set); - let (cache_log, witness) = working_set.checkpoint().freeze(); + let (cache_log, mut witness) = working_set.checkpoint().freeze(); let _ = storage - .validate_and_commit(cache_log, &witness) + .validate_and_commit(cache_log, &mut witness) .expect("ZK validation should succeed"); }; } diff --git a/crates/sovereign-sdk/module-system/sov-modules-core/Cargo.toml b/crates/sovereign-sdk/module-system/sov-modules-core/Cargo.toml index c166016bc..3fefa999b 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-core/Cargo.toml +++ b/crates/sovereign-sdk/module-system/sov-modules-core/Cargo.toml @@ -20,6 +20,7 @@ borsh = { workspace = true } derive_more = { workspace = true, features = ["display", "into"] } digest = { workspace = true } hex = { workspace = true } +hashbrown = { workspace = true } jmt = { workspace = true, optional = true } proptest = { workspace = true, optional = true } proptest-derive = { workspace = true, optional = true } diff --git a/crates/sovereign-sdk/module-system/sov-modules-core/src/common/witness.rs b/crates/sovereign-sdk/module-system/sov-modules-core/src/common/witness.rs index d40199047..71693fcae 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-core/src/common/witness.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-core/src/common/witness.rs @@ -14,17 +14,17 @@ use serde::Serialize; /// they were added via [`Witness::add_hint`]. // TODO: Refactor witness trait so it only require Serialize / Deserialize // https://github.com/Sovereign-Labs/sovereign-sdk/issues/263 -pub trait Witness: Default + Serialize + DeserializeOwned { +pub trait Witness: Default + BorshDeserialize + Serialize + DeserializeOwned { /// Adds a serializable "hint" to the witness value, which can be later /// read by the zkVM circuit. /// /// This method **SHOULD** only be called from the native execution /// environment. - fn add_hint(&self, hint: T); + fn add_hint(&mut self, hint: T); /// Retrieves a "hint" from the witness value. - fn get_hint(&self) -> T; + fn get_hint(&mut self) -> T; /// Adds all hints from `rhs` to `self`. - fn merge(&self, rhs: &Self); + fn merge(&mut self, rhs: &mut Self); } diff --git a/crates/sovereign-sdk/module-system/sov-modules-core/src/module/dispatch.rs b/crates/sovereign-sdk/module-system/sov-modules-core/src/module/dispatch.rs index 51f9e6e92..6abfd8834 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-core/src/module/dispatch.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-core/src/module/dispatch.rs @@ -1,6 +1,6 @@ //! Runtime call message definitions. -use sov_rollup_interface::maybestd::io; +use borsh::io; use crate::common::ModuleError; use crate::module::{CallResponse, Context, Spec}; diff --git a/crates/sovereign-sdk/module-system/sov-modules-core/src/module/spec.rs b/crates/sovereign-sdk/module-system/sov-modules-core/src/module/spec.rs index 6ea438658..402a256a0 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-core/src/module/spec.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-core/src/module/spec.rs @@ -19,7 +19,7 @@ use crate::storage::Storage; /// while a rollup running in an elliptic-curve based SNARK such as `Placeholder` from the =nil; foundation might /// prefer a Pedersen hash. By using a generic Context and Spec, a rollup developer can trivially customize their /// code for either (or both!) of these environments without touching their module implementations. -pub trait Spec { +pub trait Spec: BorshDeserialize + BorshSerialize { /// The Address type used on the rollup. Typically calculated as the hash of a public key. #[cfg(all(feature = "native", feature = "std"))] type Address: RollupAddress diff --git a/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/cache.rs b/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/cache.rs index 67978193c..befad747a 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/cache.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/cache.rs @@ -3,9 +3,9 @@ use alloc::vec::Vec; use core::fmt; -use sov_rollup_interface::maybestd::collections::hash_map::Entry; -use sov_rollup_interface::maybestd::collections::HashMap; -use sov_rollup_interface::maybestd::RefCount; +use hashbrown::hash_map::Entry; +use hashbrown::HashMap; +use sov_rollup_interface::RefCount; use crate::common::{MergeError, ReadError}; use crate::storage::{Storage, StorageKey, StorageValue}; @@ -385,7 +385,7 @@ impl StorageInternalCache { &mut self, key: &StorageKey, value_reader: &S, - witness: &S::Witness, + witness: &mut S::Witness, ) -> Option { let cache_key = key.to_cache_key_version(self.version); let cache_value = self.get_value_from_cache(&cache_key); @@ -475,7 +475,7 @@ impl From for OrderedReadsAndWrites { #[cfg(test)] mod tests { use proptest::prelude::*; - use sov_rollup_interface::maybestd::RefCount; + use sov_rollup_interface::RefCount; use super::*; diff --git a/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/mod.rs b/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/mod.rs index 2d29bd88e..250dbe5c0 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/mod.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/mod.rs @@ -6,8 +6,8 @@ use core::fmt; use borsh::{BorshDeserialize, BorshSerialize}; use serde::de::DeserializeOwned; use serde::Serialize; -use sov_rollup_interface::maybestd::RefCount; use sov_rollup_interface::stf::StateDiff; +use sov_rollup_interface::RefCount; use crate::common::{AlignedVec, Prefix, Version, Witness}; @@ -214,7 +214,7 @@ pub trait Storage: Clone { &self, key: &StorageKey, version: Option, - witness: &Self::Witness, + witness: &mut Self::Witness, ) -> Option; /// Returns the value corresponding to the key or None if key is absent. @@ -232,7 +232,7 @@ pub trait Storage: Clone { fn compute_state_update( &self, state_accesses: OrderedReadsAndWrites, - witness: &Self::Witness, + witness: &mut Self::Witness, ) -> Result< ( Self::Root, @@ -249,7 +249,7 @@ pub trait Storage: Clone { fn validate_and_commit_with_accessory_update( &self, state_accesses: OrderedReadsAndWrites, - witness: &Self::Witness, + witness: &mut Self::Witness, accessory_update: &OrderedReadsAndWrites, ) -> Result { let (root_hash, node_batch, _) = self.compute_state_update(state_accesses, witness)?; @@ -265,7 +265,7 @@ pub trait Storage: Clone { fn validate_and_commit( &self, state_accesses: OrderedReadsAndWrites, - witness: &Self::Witness, + witness: &mut Self::Witness, ) -> Result { Self::validate_and_commit_with_accessory_update( self, diff --git a/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/scratchpad.rs b/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/scratchpad.rs index 6f8e9c510..382877ecf 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/scratchpad.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-core/src/storage/scratchpad.rs @@ -3,8 +3,8 @@ use alloc::vec::Vec; use core::{fmt, mem}; +use hashbrown::HashMap; pub use kernel_state::{KernelWorkingSet, VersionedWorkingSet}; -use sov_rollup_interface::maybestd::collections::HashMap; use sov_rollup_interface::stf::Event; use crate::archival_state::{ArchivalAccessoryWorkingSet, ArchivalJmtWorkingSet}; @@ -188,7 +188,7 @@ impl fmt::Debug for Delta { impl StateReaderAndWriter for Delta { fn get(&mut self, key: &StorageKey) -> Option { - self.cache.get_or_fetch(key, &self.inner, &self.witness) + self.cache.get_or_fetch(key, &self.inner, &mut self.witness) } fn set(&mut self, key: &StorageKey, value: StorageValue) { diff --git a/crates/sovereign-sdk/module-system/sov-modules-macros/src/dispatch/message_codec.rs b/crates/sovereign-sdk/module-system/sov-modules-macros/src/dispatch/message_codec.rs index 57f27e915..26dcedb6a 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-macros/src/dispatch/message_codec.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-macros/src/dispatch/message_codec.rs @@ -25,7 +25,7 @@ impl<'a> StructDef<'a> { #[doc = #call_doc] fn encode_call(data: <#ty as sov_modules_api::Module>::CallMessage) -> std::vec::Vec { let call = #call_enum:: #ty_generics ::#variant(data); - ::borsh::BorshSerialize::try_to_vec(&call).unwrap() + ::borsh::to_vec(&call).unwrap() } } } diff --git a/crates/sovereign-sdk/module-system/sov-modules-macros/tests/rpc/expose_rpc_associated_types_nested.rs b/crates/sovereign-sdk/module-system/sov-modules-macros/tests/rpc/expose_rpc_associated_types_nested.rs index a36b568df..cf44a4a25 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-macros/tests/rpc/expose_rpc_associated_types_nested.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-macros/tests/rpc/expose_rpc_associated_types_nested.rs @@ -1,3 +1,4 @@ +use borsh::{BorshDeserialize, BorshSerialize}; use jsonrpsee::core::RpcResult; use sov_modules_api::default_context::ZkDefaultContext; use sov_modules_api::macros::{expose_rpc, rpc_gen, DefaultRuntime}; @@ -11,7 +12,7 @@ pub trait Message: 'static { type Caller: std::fmt::Display; type Data: Data; } -pub trait TestSpec: 'static { +pub trait TestSpec: 'static + BorshDeserialize + BorshSerialize { type Message: Message; } @@ -101,7 +102,7 @@ use my_module::query::{QueryModuleRpcImpl, QueryModuleRpcServer}; #[expose_rpc] #[derive(Genesis, DispatchCall, MessageCodec, DefaultRuntime)] -#[serialization(borsh::BorshDeserialize, borsh::BorshSerialize)] +#[serialization(BorshDeserialize, BorshSerialize)] struct Runtime { pub first: my_module::QueryModule::Message as Message>::Data>, } @@ -113,6 +114,7 @@ impl Message for ActualMessage { type Data = u32; } +#[derive(BorshDeserialize, BorshSerialize)] struct ActualSpec; impl TestSpec for ActualSpec { diff --git a/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/lib.rs b/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/lib.rs index d4dd86fd6..9947631cd 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/lib.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/lib.rs @@ -6,7 +6,7 @@ mod stf_blueprint; mod tx_verifier; pub use batch::Batch; -use borsh::{BorshDeserialize, BorshSerialize}; +use borsh::BorshDeserialize; use itertools::Itertools; use rs_merkle::algorithms::Sha256; use rs_merkle::MerkleTree; @@ -246,7 +246,7 @@ where soft_batch.timestamp(), ); - let unsigned_raw = unsigned.try_to_vec().unwrap(); + let unsigned_raw = borsh::to_vec(&unsigned).unwrap(); // check the claimed hash assert_eq!( @@ -309,10 +309,10 @@ where // Save checkpoint let mut checkpoint = working_set.checkpoint(); - let (cache_log, witness) = checkpoint.freeze(); + let (cache_log, mut witness) = checkpoint.freeze(); let (root_hash, state_update, state_diff) = pre_state - .compute_state_update(cache_log, &witness) + .compute_state_update(cache_log, &mut witness) .expect("jellyfish merkle tree update must succeed"); let mut working_set = checkpoint.to_revertable(); @@ -372,10 +372,10 @@ where .expect("Runtime initialization must succeed"); let mut checkpoint = working_set.checkpoint(); - let (log, witness) = checkpoint.freeze(); + let (log, mut witness) = checkpoint.freeze(); let (genesis_hash, state_update, _) = pre_state - .compute_state_update(log, &witness) + .compute_state_update(log, &mut witness) .expect("Storage update must succeed"); let mut working_set = checkpoint.to_revertable(); @@ -635,7 +635,7 @@ fn verify_soft_batch_signature( signature: &[u8], sequencer_public_key: &[u8], ) -> Result<(), anyhow::Error> { - let message = unsigned_soft_confirmation.try_to_vec().unwrap(); + let message = borsh::to_vec(&unsigned_soft_confirmation).unwrap(); let signature = C::Signature::try_from(signature)?; diff --git a/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/stf_blueprint.rs b/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/stf_blueprint.rs index bc67d7827..51d81c655 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/stf_blueprint.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/stf_blueprint.rs @@ -1,6 +1,5 @@ use std::marker::PhantomData; -use borsh::BorshSerialize; use sov_modules_api::hooks::{ApplySoftConfirmationError, HookSoftConfirmationInfo}; use sov_modules_api::{ native_debug, native_error, Context, DaSpec, DispatchCall, StateCheckpoint, WorkingSet, @@ -130,7 +129,7 @@ where let receipt = TransactionReceipt { tx_hash: raw_tx_hash, - body_to_save: Some(tx.clone().try_to_vec().unwrap()), + body_to_save: Some(borsh::to_vec(&tx).unwrap()), events, receipt: tx_effect, }; diff --git a/crates/sovereign-sdk/module-system/sov-state/src/codec/borsh_codec.rs b/crates/sovereign-sdk/module-system/sov-state/src/codec/borsh_codec.rs index 10d15cf15..b07205683 100644 --- a/crates/sovereign-sdk/module-system/sov-state/src/codec/borsh_codec.rs +++ b/crates/sovereign-sdk/module-system/sov-state/src/codec/borsh_codec.rs @@ -13,7 +13,7 @@ where K: BorshSerialize + BorshDeserialize, { fn encode_key(&self, value: &K) -> Vec { - value.try_to_vec().expect("Failed to serialize key") + borsh::to_vec(value).expect("Failed to serialize key") } } @@ -24,11 +24,11 @@ where type Error = std::io::Error; fn encode_value(&self, value: &V) -> Vec { - value.try_to_vec().expect("Failed to serialize value") + borsh::to_vec(value).expect("Failed to serialize value") } fn try_decode_value(&self, bytes: &[u8]) -> Result { - V::try_from_slice(bytes) + borsh::from_slice(bytes) } } @@ -52,6 +52,6 @@ where T: BorshSerialize, { fn encode_key_like(&self, borrowed: &[T]) -> Vec { - borrowed.try_to_vec().unwrap() + borsh::to_vec(borrowed).unwrap() } } diff --git a/crates/sovereign-sdk/module-system/sov-state/src/prover_storage.rs b/crates/sovereign-sdk/module-system/sov-state/src/prover_storage.rs index 91cc313a2..4a40e7025 100644 --- a/crates/sovereign-sdk/module-system/sov-state/src/prover_storage.rs +++ b/crates/sovereign-sdk/module-system/sov-state/src/prover_storage.rs @@ -84,7 +84,7 @@ impl Storage for ProverStorage { &self, key: &StorageKey, version: Option, - witness: &Self::Witness, + witness: &mut Self::Witness, ) -> Option { let val = self.read_value(key, version); witness.add_hint(val.clone()); @@ -103,7 +103,7 @@ impl Storage for ProverStorage { fn compute_state_update( &self, state_accesses: OrderedReadsAndWrites, - witness: &Self::Witness, + witness: &mut Self::Witness, ) -> Result<(Self::Root, Self::StateUpdate, StateDiff), anyhow::Error> { let latest_version = self.db.get_next_version() - 1; let jmt = JellyfishMerkleTree::<_, S::Hasher>::new(&self.db); diff --git a/crates/sovereign-sdk/module-system/sov-state/src/witness.rs b/crates/sovereign-sdk/module-system/sov-state/src/witness.rs index d3e4dc5dc..5f2b6b537 100644 --- a/crates/sovereign-sdk/module-system/sov-state/src/witness.rs +++ b/crates/sovereign-sdk/module-system/sov-state/src/witness.rs @@ -1,6 +1,3 @@ -use std::sync::atomic::AtomicUsize; -use std::sync::Mutex; - use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; use sov_modules_core::Witness; @@ -20,30 +17,28 @@ use sov_modules_core::Witness; /// assert_eq!(witness.get_hint::(), 1u64); /// assert_eq!(witness.get_hint::(), 2u64); /// ``` -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Default, BorshDeserialize, BorshSerialize, Debug, Serialize, Deserialize)] pub struct ArrayWitness { - next_idx: AtomicUsize, - hints: Mutex>>, + next_idx: usize, + hints: Vec>, } impl Witness for ArrayWitness { - fn add_hint(&self, hint: T) { - self.hints.lock().unwrap().push(hint.try_to_vec().unwrap()) + fn add_hint(&mut self, hint: T) { + self.hints.push(borsh::to_vec(&hint).unwrap()) } - fn get_hint(&self) -> T { - let idx = self - .next_idx - .fetch_add(1, std::sync::atomic::Ordering::SeqCst); - let hints_lock = self.hints.lock().unwrap(); - T::deserialize_reader(&mut std::io::Cursor::new(&hints_lock[idx])) + fn get_hint(&mut self) -> T { + let idx = self.next_idx; + self.next_idx += 1; + T::deserialize_reader(&mut std::io::Cursor::new(&self.hints[idx])) .expect("Hint deserialization should never fail") } - fn merge(&self, rhs: &Self) { - let rhs_next_idx = rhs.next_idx.load(std::sync::atomic::Ordering::SeqCst); - let mut lhs_hints_lock = self.hints.lock().unwrap(); - let mut rhs_hints_lock = rhs.hints.lock().unwrap(); + fn merge(&mut self, rhs: &mut Self) { + let rhs_next_idx = rhs.next_idx; + let lhs_hints_lock = &mut self.hints; + let rhs_hints_lock = &mut rhs.hints; lhs_hints_lock.extend(rhs_hints_lock.drain(rhs_next_idx..)) } } diff --git a/crates/sovereign-sdk/module-system/sov-state/src/zk_storage.rs b/crates/sovereign-sdk/module-system/sov-state/src/zk_storage.rs index 8fc0ab5a9..b6d4f5dfb 100644 --- a/crates/sovereign-sdk/module-system/sov-state/src/zk_storage.rs +++ b/crates/sovereign-sdk/module-system/sov-state/src/zk_storage.rs @@ -48,7 +48,7 @@ impl Storage for ZkStorage { &self, _key: &StorageKey, _version: Option, - witness: &Self::Witness, + witness: &mut Self::Witness, ) -> Option { witness.get_hint() } @@ -57,7 +57,7 @@ impl Storage for ZkStorage { fn compute_state_update( &self, state_accesses: OrderedReadsAndWrites, - witness: &Self::Witness, + witness: &mut Self::Witness, ) -> Result<(Self::Root, Self::StateUpdate, StateDiff), anyhow::Error> { let prev_state_root = witness.get_hint(); diff --git a/crates/sovereign-sdk/module-system/utils/sov-data-generators/src/lib.rs b/crates/sovereign-sdk/module-system/utils/sov-data-generators/src/lib.rs index 68ede0641..6b10e5598 100644 --- a/crates/sovereign-sdk/module-system/utils/sov-data-generators/src/lib.rs +++ b/crates/sovereign-sdk/module-system/utils/sov-data-generators/src/lib.rs @@ -1,6 +1,5 @@ use std::rc::Rc; -use borsh::ser::BorshSerialize; use sov_mock_da::verifier::MockDaSpec; use sov_mock_da::{MockAddress, MockBlob}; use sov_modules_api::transaction::Transaction; @@ -17,7 +16,7 @@ pub fn new_test_blob_from_batch( hash: [u8; 32], ) -> ::BlobTransaction { let address = MockAddress::try_from(address).unwrap(); - let data = batch.try_to_vec().unwrap(); + let data = borsh::to_vec(&batch).unwrap(); MockBlob::new(data, address, hash) } @@ -104,7 +103,7 @@ pub trait MessageGenerator { ); serialized_messages.push(RawTx { - data: tx.try_to_vec().unwrap(), + data: borsh::to_vec(&tx).unwrap(), }) } serialized_messages diff --git a/crates/sovereign-sdk/rollup-interface/src/lib.rs b/crates/sovereign-sdk/rollup-interface/src/lib.rs index cbaeeac0b..f36ba6bc1 100644 --- a/crates/sovereign-sdk/rollup-interface/src/lib.rs +++ b/crates/sovereign-sdk/rollup-interface/src/lib.rs @@ -19,18 +19,10 @@ pub use state_machine::*; mod node; +#[cfg(not(target_has_atomic = "ptr"))] +pub use alloc::rc::Rc as RefCount; +#[cfg(target_has_atomic = "ptr")] +pub use alloc::sync::Arc as RefCount; + pub use node::*; pub use {anyhow, digest}; - -/// A facade for the `std` crate. -pub mod maybestd { - #[cfg(not(target_has_atomic = "ptr"))] - pub use alloc::rc::Rc as RefCount; - // sync will be available only when the target supports atomic operations - #[cfg(target_has_atomic = "ptr")] - pub use alloc::sync; - #[cfg(target_has_atomic = "ptr")] - pub use alloc::sync::Arc as RefCount; - - pub use borsh::maybestd::{borrow, boxed, collections, format, io, string, vec}; -} diff --git a/crates/sovereign-sdk/rollup-interface/src/node/rpc/mod.rs b/crates/sovereign-sdk/rollup-interface/src/node/rpc/mod.rs index 5a9cfa864..a97ece546 100644 --- a/crates/sovereign-sdk/rollup-interface/src/node/rpc/mod.rs +++ b/crates/sovereign-sdk/rollup-interface/src/node/rpc/mod.rs @@ -1,6 +1,11 @@ //! The rpc module defines types and traits for querying chain history //! via an RPC interface. + +extern crate alloc; + use alloc::collections::BTreeMap; +use alloc::string::String; +use alloc::vec::Vec; use core::marker::PhantomData; use borsh::{BorshDeserialize, BorshSerialize}; @@ -9,8 +14,6 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use crate::da::SequencerCommitment; -use crate::maybestd::string::String; -use crate::maybestd::vec::Vec; #[cfg(feature = "native")] use crate::stf::Event; use crate::stf::EventKey; @@ -612,6 +615,10 @@ pub trait LedgerRpcProvider { pub mod utils { /// Serialization and deserialization logic for `0x`-prefixed hex strings. pub mod rpc_hex { + extern crate alloc; + + use alloc::format; + use alloc::string::String; use core::fmt; use core::marker::PhantomData; @@ -619,9 +626,6 @@ pub mod utils { use serde::de::{Error, Visitor}; use serde::{Deserializer, Serializer}; - use crate::maybestd::format; - use crate::maybestd::string::String; - /// Serializes `data` as hex string using lowercase characters and prefixing with '0x'. /// /// Lowercase characters are used (e.g. `f9b4ca`). The resulting string's length @@ -686,9 +690,6 @@ pub mod utils { mod rpc_hex_tests { use serde::{Deserialize, Serialize}; - use crate::maybestd::vec; - use crate::maybestd::vec::Vec; - #[derive(Serialize, Deserialize, PartialEq, Debug)] struct TestStruct { #[serde(with = "super::utils::rpc_hex")] diff --git a/crates/sovereign-sdk/rollup-interface/src/node/services/batch_builder.rs b/crates/sovereign-sdk/rollup-interface/src/node/services/batch_builder.rs index 90037aada..3524dc207 100644 --- a/crates/sovereign-sdk/rollup-interface/src/node/services/batch_builder.rs +++ b/crates/sovereign-sdk/rollup-interface/src/node/services/batch_builder.rs @@ -1,6 +1,8 @@ //! This module defines the trait that is used to build batches of transactions. -use crate::maybestd::vec::Vec; +extern crate alloc; + +use alloc::vec::Vec; /// BlockBuilder trait is responsible for managing mempool and building batches. pub trait BatchBuilder { diff --git a/crates/sovereign-sdk/rollup-interface/src/node/services/da.rs b/crates/sovereign-sdk/rollup-interface/src/node/services/da.rs index dbf70e130..90fd6a6a1 100644 --- a/crates/sovereign-sdk/rollup-interface/src/node/services/da.rs +++ b/crates/sovereign-sdk/rollup-interface/src/node/services/da.rs @@ -10,8 +10,6 @@ use tokio::sync::oneshot::Sender as OneshotSender; use crate::da::BlockHeaderTrait; #[cfg(feature = "native")] use crate::da::{DaSpec, DaVerifier}; -#[cfg(feature = "native")] -use crate::maybestd::vec::Vec; use crate::zk::ValidityCondition; /// This type represents a queued request to send_transaction diff --git a/crates/sovereign-sdk/rollup-interface/src/state_machine/da.rs b/crates/sovereign-sdk/rollup-interface/src/state_machine/da.rs index 86f6128ff..ec9c0bd24 100644 --- a/crates/sovereign-sdk/rollup-interface/src/state_machine/da.rs +++ b/crates/sovereign-sdk/rollup-interface/src/state_machine/da.rs @@ -32,7 +32,9 @@ pub enum DaData { } /// A specification for the types used by a DA layer. -pub trait DaSpec: 'static + Debug + PartialEq + Eq + Clone { +pub trait DaSpec: + 'static + BorshDeserialize + BorshSerialize + Debug + PartialEq + Eq + Clone +{ /// The hash of a DA layer block type SlotHash: BlockHashTrait; @@ -49,13 +51,23 @@ pub trait DaSpec: 'static + Debug + PartialEq + Eq + Clone { type ValidityCondition: ValidityCondition + Send + Sync; /// A proof that each tx in a set of blob transactions is included in a given block. - type InclusionMultiProof: Serialize + DeserializeOwned + Send + Sync; + type InclusionMultiProof: BorshDeserialize + + BorshSerialize + + Serialize + + DeserializeOwned + + Send + + Sync; /// A proof that a claimed set of transactions is complete. /// For example, this could be a range proof demonstrating that /// the provided BlobTransactions represent the entire contents /// of Celestia namespace in a given block - type CompletenessProof: Serialize + DeserializeOwned + Send + Sync; + type CompletenessProof: BorshDeserialize + + BorshSerialize + + Serialize + + DeserializeOwned + + Send + + Sync; /// The parameters of the rollup which are baked into the state-transition function. /// For example, this could include the namespace of the rollup on Celestia. @@ -157,7 +169,9 @@ impl CountedBufReader { /// will slash the sequencer and exit early - so it only cares about the content of the blob up to that point. /// /// This trait allows the DaVerifier to track which data was read by the rollup, and only verify the relevant data. -pub trait BlobReaderTrait: Serialize + DeserializeOwned + Send + Sync + 'static { +pub trait BlobReaderTrait: + BorshDeserialize + BorshSerialize + Serialize + DeserializeOwned + Send + Sync + 'static +{ /// The type used to represent addresses on the DA layer. type Address: BasicAddress; @@ -202,12 +216,14 @@ pub trait BlobReaderTrait: Serialize + DeserializeOwned + Send + Sync + 'static /// Trait with collection of trait bounds for a block hash. pub trait BlockHashTrait: // so it is compatible with StorageManager implementation? - Serialize + DeserializeOwned + PartialEq + Debug + Send + Sync + Clone + Eq + Into<[u8; 32]> + core::hash::Hash + BorshDeserialize + BorshSerialize + Serialize + DeserializeOwned + PartialEq + Debug + Send + Sync + Clone + Eq + Into<[u8; 32]> + core::hash::Hash { } /// A block header, typically used in the context of an underlying DA blockchain. -pub trait BlockHeaderTrait: PartialEq + Debug + Clone + Serialize + DeserializeOwned { +pub trait BlockHeaderTrait: + PartialEq + Debug + Clone + BorshSerialize + BorshDeserialize + Serialize + DeserializeOwned +{ /// Each block header must have a unique canonical hash. type Hash: Clone + core::fmt::Display + Into<[u8; 32]>; diff --git a/crates/sovereign-sdk/rollup-interface/src/state_machine/soft_confirmation.rs b/crates/sovereign-sdk/rollup-interface/src/state_machine/soft_confirmation.rs index fe2d5394d..1695b268e 100644 --- a/crates/sovereign-sdk/rollup-interface/src/state_machine/soft_confirmation.rs +++ b/crates/sovereign-sdk/rollup-interface/src/state_machine/soft_confirmation.rs @@ -1,13 +1,14 @@ //! Defines traits and types used by the rollup to verify claims about the //! soft confirmation +extern crate alloc; + +use alloc::vec::Vec; use core::fmt::Debug; use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; -use crate::maybestd::vec::Vec; - /// Contains raw transactions and information about the soft confirmation block #[derive(Debug, PartialEq, Clone, BorshDeserialize, BorshSerialize, Serialize, Deserialize)] pub struct UnsignedSoftConfirmationBatch { @@ -174,7 +175,7 @@ impl SignedSoftConfirmationBatch { /// Borsh serialized data pub fn full_data(&mut self) -> Vec { - self.try_to_vec().unwrap() + borsh::to_vec(self).unwrap() } /// L1 fee rate diff --git a/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs b/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs index 8774b1d2d..2cd0045dd 100644 --- a/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs +++ b/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs @@ -3,7 +3,11 @@ //! //! The most important trait in this module is the [`StateTransitionFunction`], which defines the //! main event loop of the rollup. + +extern crate alloc; + use alloc::collections::VecDeque; +use alloc::vec::Vec; use core::fmt::Debug; use core::marker::PhantomData; @@ -12,7 +16,6 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use crate::da::DaSpec; -use crate::maybestd::vec::Vec; use crate::soft_confirmation::SignedSoftConfirmationBatch; use crate::zk::{CumulativeStateDiff, ValidityCondition, Zkvm}; @@ -139,7 +142,13 @@ pub struct SlotResult { /// - blob: Non serialised batch or anything else that can be posted on DA layer, like attestation or proof. pub trait StateTransitionFunction { /// Root hash of state merkle tree - type StateRoot: Serialize + DeserializeOwned + Clone + AsRef<[u8]> + Debug; + type StateRoot: BorshDeserialize + + BorshSerialize + + Serialize + + DeserializeOwned + + Clone + + AsRef<[u8]> + + Debug; /// The initial params of the rollup. type GenesisParams; @@ -158,7 +167,7 @@ pub trait StateTransitionFunction { /// Witness is a data that is produced during actual batch execution /// or validated together with proof during verification - type Witness: Default + Serialize + DeserializeOwned; + type Witness: Default + BorshDeserialize + Serialize + DeserializeOwned; /// The validity condition that must be verified outside of the Vm type Condition: ValidityCondition; diff --git a/crates/sovereign-sdk/rollup-interface/src/state_machine/stf/fuzzing.rs b/crates/sovereign-sdk/rollup-interface/src/state_machine/stf/fuzzing.rs index 1650b22f6..c9e7ed62c 100644 --- a/crates/sovereign-sdk/rollup-interface/src/state_machine/stf/fuzzing.rs +++ b/crates/sovereign-sdk/rollup-interface/src/state_machine/stf/fuzzing.rs @@ -8,8 +8,6 @@ use proptest::prelude::{any, Arbitrary}; use proptest::strategy::{BoxedStrategy, Strategy}; use super::{BatchReceipt, Event, TransactionReceipt}; -use crate::maybestd::boxed::Box; -use crate::maybestd::vec::Vec; /// An object-safe hashing trait, which is blanket implemented for all /// [`digest::Digest`] implementors. diff --git a/crates/sovereign-sdk/rollup-interface/src/state_machine/zk/mod.rs b/crates/sovereign-sdk/rollup-interface/src/state_machine/zk/mod.rs index 332fcc4ee..b9180be97 100644 --- a/crates/sovereign-sdk/rollup-interface/src/state_machine/zk/mod.rs +++ b/crates/sovereign-sdk/rollup-interface/src/state_machine/zk/mod.rs @@ -6,6 +6,9 @@ //! For a detailed example showing how to implement these traits, see the //! [risc0 adapter](https://github.com/Sovereign-Labs/sovereign-sdk/tree/main/adapters/risc0) //! maintained by the Sovereign Labs team. + +extern crate alloc; + use alloc::collections::{BTreeMap, VecDeque}; use alloc::vec::Vec; use core::fmt::Debug; @@ -32,7 +35,7 @@ pub trait ZkvmHost: Zkvm + Clone { /// The associated guest type type Guest: ZkvmGuest; /// Give the guest a piece of advice non-deterministically - fn add_hint(&mut self, item: T); + fn add_hint(&mut self, item: T); /// Simulate running the guest using the provided hints. /// @@ -48,7 +51,7 @@ pub trait ZkvmHost: Zkvm + Clone { fn run(&mut self, with_proof: bool) -> Result; /// Extracts public input form the proof. - fn extract_output( + fn extract_output( proof: &Proof, ) -> Result, Self::Error>; } @@ -81,9 +84,9 @@ pub trait Zkvm: Send + Sync { /// A trait which is accessible from within a zkVM program. pub trait ZkvmGuest: Zkvm + Send + Sync { /// Obtain "advice" non-deterministically from the host - fn read_from_host(&self) -> T; + fn read_from_host(&self) -> T; /// Add a public output to the zkVM proof - fn commit(&self, item: &T); + fn commit(&self, item: &T); } /// This trait is implemented on the struct/enum which expresses the validity condition @@ -153,7 +156,7 @@ pub trait Matches { fn matches(&self, other: &T) -> bool; } -#[derive(Serialize, BorshDeserialize, BorshSerialize, Deserialize)] +#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize)] // Prevent serde from generating spurious trait bounds. The correct serde bounds are already enforced by the // StateTransitionFunction, DA, and Zkvm traits. #[serde(bound = "StateRoot: Serialize + DeserializeOwned, Witness: Serialize + DeserializeOwned")] diff --git a/crates/sovereign-sdk/utils/rng-da-service/src/lib.rs b/crates/sovereign-sdk/utils/rng-da-service/src/lib.rs index 2f9db9f1a..6ebc0eb2a 100644 --- a/crates/sovereign-sdk/utils/rng-da-service/src/lib.rs +++ b/crates/sovereign-sdk/utils/rng-da-service/src/lib.rs @@ -1,8 +1,9 @@ use std::env; use async_trait::async_trait; -use borsh::ser::BorshSerialize; +use borsh::{BorshDeserialize, BorshSerialize}; use demo_stf::runtime::Runtime; +use serde::{Deserialize, Serialize}; use sov_bank::{Bank, Coins}; use sov_mock_da::{ MockAddress, MockBlob, MockBlock, MockBlockHeader, MockHash, MockValidityCond, @@ -43,7 +44,9 @@ impl RngDaService { } /// A simple DaSpec for a random number generator. -#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug, Clone, Default)] +#[derive( + BorshDeserialize, BorshSerialize, Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Default, +)] pub struct RngDaSpec; impl DaSpec for RngDaSpec { @@ -236,10 +239,10 @@ pub fn generate_transfers(n: usize, start_nonce: u64) -> Vec { DEFAULT_CHAIN_ID, start_nonce + (i as u64), ); - let ser_tx = tx.try_to_vec().unwrap(); + let ser_tx = borsh::to_vec(&tx).unwrap(); message_vec.push(ser_tx) } - message_vec.try_to_vec().unwrap() + borsh::to_vec(&message_vec).unwrap() } pub fn generate_create_token_payload(start_nonce: u64) -> Vec { @@ -258,9 +261,9 @@ pub fn generate_create_token_payload(start_nonce: u64) -> Vec { as EncodeCall>>::encode_call(msg); let tx = Transaction::::new_signed_tx(&pk, enc_msg, DEFAULT_CHAIN_ID, start_nonce); - let ser_tx = tx.try_to_vec().unwrap(); + let ser_tx = borsh::to_vec(&tx).unwrap(); message_vec.push(ser_tx); - message_vec.try_to_vec().unwrap() + borsh::to_vec(&message_vec).unwrap() } #[cfg(test)] diff --git a/deny.toml b/deny.toml index d8c83ffe0..2b8c1a5a6 100644 --- a/deny.toml +++ b/deny.toml @@ -43,6 +43,5 @@ deny = [{ name = "native-tls" }, { name = "openssl" }] [advisories] ignore = [ - "RUSTSEC-2023-0033", # borsh 0.10.3 "RUSTSEC-2024-0344", # curve25519-dalek 4.1.2 ]