From 9bfa057b9bbaf28bfde4ef5a4a0c7b78861a3b4b Mon Sep 17 00:00:00 2001 From: Gabriel Coutinho de Paula Date: Mon, 16 Dec 2024 09:23:04 -0300 Subject: [PATCH] feat(cartesi-machine): update machine bindings --- Cargo.lock | 551 ++++--- Cargo.toml | 5 +- .../node/blockchain-reader/Cargo.toml | 3 +- .../node/blockchain-reader/src/lib.rs | 22 +- .../node/machine-runner/src/error.rs | 2 +- .../node/machine-runner/src/lib.rs | 24 +- common-rs/merkle/Cargo.toml | 4 +- common-rs/merkle/src/digest/keccak.rs | 50 +- common-rs/merkle/src/digest/mod.rs | 6 +- machine/emulator | 2 +- .../cartesi-machine-sys/Cargo.toml | 2 +- .../cartesi-machine-sys/build.rs | 73 +- .../cartesi-machine-sys/src/lib.rs | 4 +- .../rust-bindings/cartesi-machine/Cargo.toml | 11 +- .../cartesi-machine/src/config/machine.rs | 566 +++++++ .../cartesi-machine/src/config/mod.rs | 5 + .../cartesi-machine/src/config/runtime.rs | 32 + .../cartesi-machine/src/configuration.rs | 115 -- .../cartesi-machine/src/constants.rs | 160 +- .../cartesi-machine/src/error.rs | 21 + .../cartesi-machine/src/errors.rs | 58 - .../rust-bindings/cartesi-machine/src/hash.rs | 34 - .../rust-bindings/cartesi-machine/src/lib.rs | 16 +- .../rust-bindings/cartesi-machine/src/log.rs | 184 --- .../cartesi-machine/src/machine.rs | 1343 ++++++++++------- .../cartesi-machine/src/proof.rs | 52 - .../cartesi-machine/src/types/access_proof.rs | 91 ++ .../src/types/base64_decode.rs | 299 ++++ .../cartesi-machine/src/types/cmio.rs | 155 ++ .../cartesi-machine/src/types/memory_proof.rs | 31 + .../cartesi-machine/src/types/memory_range.rs | 13 + .../cartesi-machine/src/types/mod.rs | 20 + .../cartesi-machine/src/utils.rs | 14 - prt/client-rs/core/src/machine/instance.rs | 102 +- 34 files changed, 2540 insertions(+), 1530 deletions(-) create mode 100644 machine/rust-bindings/cartesi-machine/src/config/machine.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/config/mod.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/config/runtime.rs delete mode 100644 machine/rust-bindings/cartesi-machine/src/configuration.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/error.rs delete mode 100644 machine/rust-bindings/cartesi-machine/src/errors.rs delete mode 100644 machine/rust-bindings/cartesi-machine/src/hash.rs delete mode 100644 machine/rust-bindings/cartesi-machine/src/log.rs delete mode 100644 machine/rust-bindings/cartesi-machine/src/proof.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/types/access_proof.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/types/base64_decode.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/types/cmio.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/types/memory_proof.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/types/memory_range.rs create mode 100644 machine/rust-bindings/cartesi-machine/src/types/mod.rs delete mode 100644 machine/rust-bindings/cartesi-machine/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index e60d256c..5294299f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -60,6 +60,7 @@ dependencies = [ "alloy-node-bindings", "alloy-provider", "alloy-rpc-client", + "alloy-rpc-types", "alloy-serde", "alloy-signer", "alloy-signer-local", @@ -69,9 +70,9 @@ dependencies = [ [[package]] name = "alloy-chains" -version = "0.1.51" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e0f0136c085132939da6b753452ebed4efaa73fe523bb855b10c199c2ebfaf" +checksum = "4ab9d1367c6ffb90c93fb4a9a4989530aa85112438c6f73a734067255d348469" dependencies = [ "alloy-primitives", "num_enum", @@ -126,14 +127,14 @@ dependencies = [ "alloy-transport", "futures", "futures-util", - "thiserror 2.0.9", + "thiserror", ] [[package]] name = "alloy-core" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3fdddfc89197319b1be19875a70ced62a72bebb67e2276dad688cd59f40e70" +checksum = "648275bb59110f88cc5fa9a176845e52a554ebfebac2d21220bcda8c9220f797" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -144,9 +145,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d2ea4d7f220a19c1f8c98822026d1d26a4b75a72e1a7308d02bab1f77c9a00" +checksum = "bc9138f4f0912793642d453523c3116bd5d9e11de73b70177aa7cb3e94b98ad2" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -214,9 +215,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79c6b4bcc1067a7394b5b2aec7da1bd829c8c476b796c73eb14da34392a07a7" +checksum = "24acd2f5ba97c7a320e67217274bc81fe3c3174b8e6144ec875d9d54e760e278" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -234,7 +235,7 @@ dependencies = [ "alloy-sol-types", "serde", "serde_json", - "thiserror 2.0.9", + "thiserror", "tracing", ] @@ -260,7 +261,7 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.9", + "thiserror", ] [[package]] @@ -288,16 +289,16 @@ dependencies = [ "rand", "serde_json", "tempfile", - "thiserror 2.0.9", + "thiserror", "tracing", "url", ] [[package]] name = "alloy-primitives" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0540fd0355d400b59633c27bd4b42173e59943f28e9d3376b77a24771d432d04" +checksum = "ec878088ec6283ce1e90d280316aadd3d6ce3de06ff63d68953c855e7e447e92" dependencies = [ "alloy-rlp", "bytes", @@ -306,7 +307,6 @@ dependencies = [ "derive_more", "foldhash", "hashbrown 0.15.2", - "hex-literal", "indexmap", "itoa", "k256", @@ -315,7 +315,7 @@ dependencies = [ "proptest", "rand", "ruint", - "rustc-hash 2.1.0", + "rustc-hash", "serde", "sha3", "tiny-keccak", @@ -355,7 +355,7 @@ dependencies = [ "schnellru", "serde", "serde_json", - "thiserror 2.0.9", + "thiserror", "tokio", "tracing", "url", @@ -364,9 +364,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f542548a609dca89fcd72b3b9f355928cf844d4363c5eed9c5273a3dd225e097" +checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -375,13 +375,13 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a833d97bf8a5f0f878daf2c8451fff7de7f9de38baa5a45d936ec718d81255a" +checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -407,6 +407,18 @@ dependencies = [ "wasmtimer", ] +[[package]] +name = "alloy-rpc-types" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3410a472ce26c457e9780f708ee6bd540b30f88f1f31fdab7a11d00bd6aa1aee" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + [[package]] name = "alloy-rpc-types-anvil" version = "0.8.3" @@ -472,7 +484,7 @@ dependencies = [ "auto_impl", "elliptic-curve", "k256", - "thiserror 2.0.9", + "thiserror", ] [[package]] @@ -488,28 +500,28 @@ dependencies = [ "async-trait", "k256", "rand", - "thiserror 2.0.9", + "thiserror", ] [[package]] name = "alloy-sol-macro" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6d1a14b4a9f6078ad9132775a2ebb465b06b387d60f7413ddc86d7bf7453408" +checksum = "8d039d267aa5cbb7732fa6ce1fd9b5e9e29368f580f80ba9d7a8450c794de4b2" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] name = "alloy-sol-macro-expander" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4436b4b96d265eb17daea26eb31525c3076d024d10901e446790afbd2f7eeaf5" +checksum = "620ae5eee30ee7216a38027dec34e0585c55099f827f92f50d11e3d2d3a4a954" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -519,16 +531,16 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f58698a18b96faa8513519de112b79a96010b4ff84264ce54a217c52a8e98b" +checksum = "ad9f7d057e00f8c5994e4ff4492b76532c51ead39353aa2ed63f8c50c0f4d52e" dependencies = [ "alloy-json-abi", "const-hex", @@ -537,15 +549,15 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.94", + "syn 2.0.96", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3d6d2c490f650c5abd65a9a583b09a8c8931c265d3a55b18a8e349dd6d9d84" +checksum = "74e60b084fe1aef8acecda2743ff2d93c18ff3eb67a2d3b12f62582a1e66ef5e" dependencies = [ "serde", "winnow", @@ -553,9 +565,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c766e4979fc19d70057150befe8e3ea3f0c4cbc6839b8eaaa250803451692305" +checksum = "c1382302752cd751efd275f4d6ef65877ddf61e0e6f5ac84ef4302b79a33a31a" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -576,7 +588,7 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.9", + "thiserror", "tokio", "tower", "tracing", @@ -656,11 +668,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -811,7 +824,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -833,29 +846,29 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] name = "auto_impl" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -899,25 +912,22 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bindgen" -version = "0.69.5" +version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", "quote", "regex", - "rustc-hash 1.1.0", + "rustc-hash", "shlex", - "syn 2.0.94", - "which", + "syn 2.0.96", ] [[package]] @@ -937,9 +947,9 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bitvec" @@ -1034,17 +1044,22 @@ dependencies = [ "alloy", "hex", "ruint", - "sha3", - "thiserror 1.0.69", + "thiserror", + "tiny-keccak", ] [[package]] name = "cartesi-machine" version = "0.1.0" dependencies = [ + "base64", "cartesi-machine-sys", + "derive_builder", "hex", - "thiserror 1.0.69", + "serde", + "serde_json", + "tempfile", + "thiserror", ] [[package]] @@ -1102,7 +1117,7 @@ dependencies = [ "rusqlite_migration", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror", "tokio", ] @@ -1117,9 +1132,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.6" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "shlex", ] @@ -1158,9 +1173,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.23" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" dependencies = [ "clap_builder", "clap_derive", @@ -1168,9 +1183,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" dependencies = [ "anstream", "anstyle", @@ -1180,14 +1195,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -1254,9 +1269,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] name = "crypto-bigint" @@ -1280,6 +1295,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.96", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.96", +] + [[package]] name = "dashmap" version = "6.1.0" @@ -1336,6 +1386,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.96", +] + [[package]] name = "derive_more" version = "1.0.0" @@ -1353,7 +1434,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", "unicode-xid", ] @@ -1386,7 +1467,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -1633,7 +1714,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -1692,10 +1773,22 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", +] + [[package]] name = "gimli" version = "0.31.1" @@ -1791,15 +1884,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "http" version = "1.2.0" @@ -2033,9 +2117,15 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.0.3" @@ -2074,14 +2164,14 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -2090,9 +2180,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is_terminal_polyfill" @@ -2109,15 +2199,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -2135,9 +2216,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -2181,12 +2262,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.169" @@ -2231,9 +2306,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" @@ -2253,9 +2328,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "lru" @@ -2286,9 +2361,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] @@ -2300,7 +2375,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -2387,14 +2462,14 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] name = "nybbles" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3409fc85ac27b27d971ea7cd1aabafd2eefa6de7e481c8d4f707225c117e81a" +checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" dependencies = [ "alloy-rlp", "const-hex", @@ -2441,7 +2516,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -2530,35 +2605,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 2.0.9", + "thiserror", "ucd-trie", ] [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -2593,12 +2668,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -2640,14 +2715,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -2688,10 +2763,10 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.0", + "rustc-hash", "rustls", "socket2", - "thiserror 2.0.9", + "thiserror", "tokio", "tracing", ] @@ -2703,14 +2778,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", - "getrandom", + "getrandom 0.2.15", "rand", "ring", - "rustc-hash 2.1.0", + "rustc-hash", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.9", + "thiserror", "tinyvec", "tracing", "web-time", @@ -2773,7 +2848,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -2888,7 +2963,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", "spin", "untrusted", @@ -2910,7 +2985,6 @@ name = "rollups-blockchain-reader" version = "0.1.0" dependencies = [ "alloy", - "alloy-rpc-types-eth", "async-recursion", "cartesi-dave-contracts", "cartesi-dave-merkle", @@ -2923,7 +2997,7 @@ dependencies = [ "rollups-state-manager", "rusqlite", "rusqlite_migration", - "thiserror 1.0.69", + "thiserror", "tokio", ] @@ -2953,7 +3027,7 @@ dependencies = [ "cartesi-rollups-contracts", "hex", "rollups-state-manager", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -2973,7 +3047,7 @@ dependencies = [ "lazy_static", "rusqlite", "rusqlite_migration", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -3038,12 +3112,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.0" @@ -3071,14 +3139,14 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.24", + "semver 1.0.25", ] [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", @@ -3089,9 +3157,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.20" +version = "0.23.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" dependencies = [ "once_cell", "ring", @@ -3165,9 +3233,9 @@ dependencies = [ [[package]] name = "schnellru" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +checksum = "356285bbf17bea63d9e52e96bd18f039672ac92b55b8cb997d6162a2a37d1649" dependencies = [ "ahash", "cfg-if", @@ -3209,9 +3277,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -3228,9 +3296,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "semver-parser" @@ -3258,14 +3326,14 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" dependencies = [ "itoa", "memchr", @@ -3433,7 +3501,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -3455,9 +3523,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.94" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -3466,14 +3534,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c74af950d86ec0f5b2ae2d7f1590bbfbcf4603a0a15742d8f98132ac4fe3efd4" +checksum = "b84e4d83a0a6704561302b917a932484e1cae2d8c6354c64be8b7bac1c1fe057" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -3493,7 +3561,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -3504,12 +3572,13 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" dependencies = [ "cfg-if", "fastrand", + "getrandom 0.3.1", "once_cell", "rustix", "windows-sys 0.59.0", @@ -3517,42 +3586,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" -dependencies = [ - "thiserror-impl 2.0.9", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.94", + "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.9" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -3600,9 +3649,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -3618,13 +3667,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -3735,7 +3784,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -3785,9 +3834,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243" [[package]] name = "unicode-xid" @@ -3832,9 +3881,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vcpkg" @@ -3872,36 +3921,46 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.49" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", @@ -3912,9 +3971,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3922,22 +3981,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasmtimer" @@ -3955,9 +4017,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -3982,18 +4044,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "windows-registry" version = "0.2.0" @@ -4108,13 +4158,22 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.21" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f5bb5257f2407a5425c6e749bfd9692192a73e70a6060516ac04f889087d68" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + [[package]] name = "write16" version = "1.0.0" @@ -4156,7 +4215,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", "synstructure", ] @@ -4178,7 +4237,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -4198,7 +4257,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", "synstructure", ] @@ -4219,7 +4278,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] [[package]] @@ -4241,5 +4300,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.96", ] diff --git a/Cargo.toml b/Cargo.toml index 8dd8ad8f..b8e4fe0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,12 +72,13 @@ cartesi-prt-core = { path = "prt/client-rs/core" } cartesi-rollups-contracts = "=2.0.0-rc.13" # eth -alloy = { version = "0.8", features = ["sol-types", "contract", "network", "reqwest", "signers", "signer-local"] } +alloy = { version = "0.8", features = ["contract", "network", "reqwest", "rpc-types", "signers", "signer-local", "sol-types"] } ruint = "1.12" +tiny-keccak = { version = "2.0", features = ["keccak"] } # error handling anyhow = "1.0" -thiserror = "1.0" +thiserror = "2.0" # async async-recursion = "1" diff --git a/cartesi-rollups/node/blockchain-reader/Cargo.toml b/cartesi-rollups/node/blockchain-reader/Cargo.toml index e83b9329..d99116dc 100644 --- a/cartesi-rollups/node/blockchain-reader/Cargo.toml +++ b/cartesi-rollups/node/blockchain-reader/Cargo.toml @@ -16,7 +16,6 @@ cartesi-dave-contracts = { workspace = true } cartesi-rollups-contracts = { workspace = true } alloy = { workspace = true } -alloy-rpc-types-eth = "0.8.0" async-recursion = { workspace = true } clap = { workspace = true } log = { workspace = true } @@ -25,7 +24,7 @@ tokio = { workspace = true } num-traits = { workspace = true } [dev-dependencies] -alloy = { workspace = true, features = ["node-bindings"] } +alloy = { workspace = true, features = ["node-bindings", "rpc-types"] } cartesi-dave-merkle = { workspace = true } cartesi-prt-core = { workspace = true } cartesi-prt-contracts = { workspace = true } diff --git a/cartesi-rollups/node/blockchain-reader/src/lib.rs b/cartesi-rollups/node/blockchain-reader/src/lib.rs index c0f4a631..8fe1be75 100644 --- a/cartesi-rollups/node/blockchain-reader/src/lib.rs +++ b/cartesi-rollups/node/blockchain-reader/src/lib.rs @@ -8,19 +8,18 @@ use alloy::{ contract::{Error, Event}, eips::BlockNumberOrTag::Finalized, hex::ToHexExt, - primitives::Address, + primitives::{Address, U256}, providers::{ network::primitives::BlockTransactionsKind, Provider, ProviderBuilder, RootProvider, }, + rpc::types::Topic, sol_types::SolEvent, transports::http::{reqwest::Url, Client, Http}, }; -use alloy_rpc_types_eth::Topic; use async_recursion::async_recursion; use clap::Parser; use error::BlockchainReaderError; use log::{info, trace}; -use num_traits::cast::ToPrimitive; use std::{ iter::Peekable, marker::{Send, Sync}, @@ -167,11 +166,11 @@ where let epoch = Epoch { epoch_number: e .epochNumber - .to_u64() + .try_into() .expect("fail to convert epoch number"), input_index_boundary: e .inputIndexUpperBound - .to_u64() + .try_into() .expect("fail to convert epoch boundary"), root_tournament: e.tournament.to_string(), }; @@ -257,12 +256,7 @@ where let mut inputs = vec![]; while let Some(input_added) = input_events_peekable.peek() { - if input_added - .index - .to_u64() - .expect("fail to convert input index") - >= input_index_boundary - { + if input_added.index >= U256::from(input_index_boundary) { break; } let input = Input { @@ -319,9 +313,9 @@ impl EventReader { current_finalized, ) .await - .map_err(|err_arr| ProviderErrors(err_arr))?; + .map_err(ProviderErrors)?; - return Ok(logs); + Ok(logs) } } @@ -362,7 +356,7 @@ impl PartitionProvider { let mut e = Event::new_sol(&self.inner, read_from) .from_block(start_block) .to_block(end_block) - .event(&E::SIGNATURE); + .event(E::SIGNATURE); if let Some(t) = topic1 { e = e.topic1(t.clone()); diff --git a/cartesi-rollups/node/machine-runner/src/error.rs b/cartesi-rollups/node/machine-runner/src/error.rs index 722ab12d..a22ef36e 100644 --- a/cartesi-rollups/node/machine-runner/src/error.rs +++ b/cartesi-rollups/node/machine-runner/src/error.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 (see LICENSE) use cartesi_dave_merkle::DigestError; -use cartesi_machine::errors::MachineError; +use cartesi_machine::error::MachineError; use rollups_state_manager::StateManager; use thiserror::Error; diff --git a/cartesi-rollups/node/machine-runner/src/lib.rs b/cartesi-rollups/node/machine-runner/src/lib.rs index c12438c6..bf60034f 100644 --- a/cartesi-rollups/node/machine-runner/src/lib.rs +++ b/cartesi-rollups/node/machine-runner/src/lib.rs @@ -13,7 +13,10 @@ use std::{ use cartesi_dave_merkle::{Digest, DigestError, MerkleBuilder}; use cartesi_machine::{ - break_reason, configuration::RuntimeConfig, hash::Hash, htif, machine::Machine, + config::runtime::RuntimeConfig, + constants::break_reason, + machine::Machine, + types::{cmio::CmioResponseReason, Hash}, }; use cartesi_prt_core::machine::constants::{LOG2_EMULATOR_SPAN, LOG2_INPUT_SPAN, LOG2_UARCH_SPAN}; use rollups_state_manager::{InputId, StateManager}; @@ -52,7 +55,7 @@ where None => (initial_machine.to_string(), 0, 0), }; - let machine = Machine::load(Path::new(&snapshot), RuntimeConfig::default())?; + let machine = Machine::load(Path::new(&snapshot), &RuntimeConfig::default())?; Ok(Self { machine, @@ -140,10 +143,7 @@ where if state_hashes.is_empty() { // no inputs in current epoch, add machine state hash repeatedly let machine_state_hash = self.add_state_hash(stride_count_in_epoch)?; - state_hashes.push(( - machine_state_hash.as_bytes().to_vec(), - stride_count_in_epoch, - )); + state_hashes.push((machine_state_hash.to_vec(), stride_count_in_epoch)); } let (computation_hash, total_repetitions) = @@ -172,7 +172,7 @@ where self.run_machine(big_steps_in_stride)?; let mut i: u64 = 0; - while !self.machine.read_iflags_y()? { + while !self.machine.iflags_y()? { self.add_state_hash(1)?; i += 1; self.run_machine(big_steps_in_stride)?; @@ -184,12 +184,12 @@ where fn feed_input(&mut self, input: &[u8]) -> Result<(), SM> { self.machine - .send_cmio_response(htif::fromhost::ADVANCE_STATE, input)?; + .send_cmio_response(CmioResponseReason::Advance, input)?; Ok(()) } fn run_machine(&mut self, cycles: u64) -> Result<(), SM> { - let mcycle = self.machine.read_mcycle()?; + let mcycle = self.machine.mcycle()?; loop { let reason = self.machine.run(mcycle + cycles)?; @@ -204,10 +204,10 @@ where } fn add_state_hash(&mut self, repetitions: u64) -> Result { - let machine_state_hash = self.machine.get_root_hash()?; + let machine_state_hash = self.machine.root_hash()?; self.state_manager .add_machine_state_hash( - machine_state_hash.as_bytes(), + &machine_state_hash, self.epoch_number, self.state_hash_index_in_epoch, repetitions, @@ -218,7 +218,7 @@ where Ok(machine_state_hash) } - fn take_snapshot(&self) -> Result<(), SM> { + fn take_snapshot(&mut self) -> Result<(), SM> { let epoch_path = self .state_dir .join("snapshots") diff --git a/common-rs/merkle/Cargo.toml b/common-rs/merkle/Cargo.toml index 2cc1af05..b389125f 100644 --- a/common-rs/merkle/Cargo.toml +++ b/common-rs/merkle/Cargo.toml @@ -15,5 +15,5 @@ alloy = { workspace = true, features = ["sol-types"] } ruint = { workspace = true } hex = "0.4" -sha3 = "0.10" -thiserror = "1.0" +tiny-keccak = { workspace = true } +thiserror = { workspace = true } diff --git a/common-rs/merkle/src/digest/keccak.rs b/common-rs/merkle/src/digest/keccak.rs index 65bc856e..df350afe 100644 --- a/common-rs/merkle/src/digest/keccak.rs +++ b/common-rs/merkle/src/digest/keccak.rs @@ -1,24 +1,60 @@ //! Keccak256 hash for the Digest Type. It's used to hash the data in the Digest. -use sha3::{Digest as Keccak256Digest, Keccak256}; +use tiny_keccak::{Hasher, Keccak}; use super::Digest; impl Digest { /// Computes the Keccak256 hash of the given data and returns a new Digest. pub fn from_data(data: &[u8]) -> Digest { - let mut keccak = Keccak256::new(); + let mut keccak = Keccak::v256(); keccak.update(data); - let digest: [u8; 32] = keccak.finalize().into(); + let mut digest: [u8; 32] = [0; 32]; + keccak.finalize(&mut digest); Digest::from(digest) } /// Joins the current Digest with another Digest to create a new Digest. pub fn join(&self, digest: &Digest) -> Digest { - let mut keccak = Keccak256::new(); - keccak.update(self.data); - keccak.update(digest.data); - let digest: [u8; 32] = keccak.finalize().into(); + let mut keccak = Keccak::v256(); + keccak.update(&self.data); + keccak.update(&digest.data); + let mut digest: [u8; 32] = [0; 32]; + keccak.finalize(&mut digest); Digest::from(digest) } } + +#[cfg(test)] +mod tests { + use super::Digest; + + fn assert_data_eq(expected_digest_hex: &str, digest: Digest) { + assert_eq!( + Digest::from_digest_hex(expected_digest_hex).expect("invalid hex"), + digest + ); + } + + #[test] + fn test_from_data() { + assert_data_eq( + "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + Digest::from_data(&[]), // cast keccak "" + ); + + assert_data_eq( + "0x6228290203658fd4987e40cbb257cabf258f9c288cdee767eaba6b234a73a2f9", + Digest::from_data("bananas".as_bytes()), // cast keccak "bananas" + ); + } + + #[test] + fn test_join() { + assert_data_eq( + "0x4441036546894c6fcf905b48b722f6b149ec0902955a6445c63cfec478568268", + // cast keccak (cast concat-hex (cast keccak "minhas") (cast keccak "bananas")) + Digest::from_data("minhas".as_bytes()).join(&Digest::from_data("bananas".as_bytes())), + ); + } +} diff --git a/common-rs/merkle/src/digest/mod.rs b/common-rs/merkle/src/digest/mod.rs index d90c8bcc..c60b468f 100644 --- a/common-rs/merkle/src/digest/mod.rs +++ b/common-rs/merkle/src/digest/mod.rs @@ -1,15 +1,13 @@ //! Definition of the [Digest] type and its associated methods. A digest is the output of a hash //! function. It's used to identify the data in the MerkleTree. -use alloy::sol_types::private::B256; +use alloy::primitives::B256; use hex::FromHex; use std::fmt; +use thiserror::Error; pub mod keccak; -use hex; -use thiserror::Error; - const HASH_SIZE: usize = 32; #[derive(Error, Debug)] diff --git a/machine/emulator b/machine/emulator index b7efb64a..b5951e42 160000 --- a/machine/emulator +++ b/machine/emulator @@ -1 +1 @@ -Subproject commit b7efb64a92c552d9307d3c7581f1de4de94ababb +Subproject commit b5951e42257c6054c4713bfface2b7c5d2b11287 diff --git a/machine/rust-bindings/cartesi-machine-sys/Cargo.toml b/machine/rust-bindings/cartesi-machine-sys/Cargo.toml index 363ded2b..40ecde5a 100644 --- a/machine/rust-bindings/cartesi-machine-sys/Cargo.toml +++ b/machine/rust-bindings/cartesi-machine-sys/Cargo.toml @@ -34,7 +34,7 @@ link-cplusplus = "1.0" [build-dependencies] -bindgen = "0.69" +bindgen = "0.71" cfg-if = "1.0" hex-literal = "0.4.1" diff --git a/machine/rust-bindings/cartesi-machine-sys/build.rs b/machine/rust-bindings/cartesi-machine-sys/build.rs index 3e898a0f..9a0af90b 100644 --- a/machine/rust-bindings/cartesi-machine-sys/build.rs +++ b/machine/rust-bindings/cartesi-machine-sys/build.rs @@ -1,27 +1,7 @@ // (c) Cartesi and individual authors (see AUTHORS) // SPDX-License-Identifier: Apache-2.0 (see LICENSE) - use std::{env, path::PathBuf, process::Command}; -mod feature_checks { - #[cfg(all(feature = "build_uarch", feature = "copy_uarch",))] - compile_error!("Features `build_uarch` and `copy_uarch` are mutually exclusive"); - - #[cfg(all(feature = "build_uarch", feature = "download_uarch"))] - compile_error!("Features `build_uarch` and `download_uarch` are mutually exclusive"); - - #[cfg(all(feature = "copy_uarch", feature = "download_uarch"))] - compile_error!("Features `copy_uarch`, and `download_uarch` are mutually exclusive"); - - #[cfg(not(any( - feature = "copy_uarch", - feature = "download_uarch", - feature = "build_uarch", - feature = "external_cartesi", - )))] - compile_error!("At least one of `build_uarch`, `copy_uarch`, `download_uarch`, and `external_cartesi` must be set"); -} - fn main() { let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); @@ -62,6 +42,7 @@ fn main() { // Generate bindings // + // find headers #[allow(clippy::needless_late_init)] let include_path; cfg_if::cfg_if! { @@ -75,32 +56,21 @@ fn main() { } }; - // machine api + // generate machine api let machine_bindings = bindgen::Builder::default() .header(include_path.join("machine-c-api.h").to_str().unwrap()) + .allowlist_item("^cm_.*") + .allowlist_item("^CM_.*") + .merge_extern_blocks(true) + .prepend_enum_name(false) + .translate_enum_integer_types(true) .generate() .expect("Unable to generate machine bindings"); - // htif constants - let htif = bindgen::Builder::default() - .header(include_path.join("htif-defines.h").to_str().unwrap()) - .generate() - .expect("Unable to generate htif bindings"); - - // pma constants - let pma = bindgen::Builder::default() - .header(include_path.join("pma-defines.h").to_str().unwrap()) - .generate() - .expect("Unable to generate pma bindings"); - // Write the bindings to the `$OUT_DIR/bindings.rs` and `$OUT_DIR/htif.rs` files. machine_bindings .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write machine bindings"); - htif.write_to_file(out_path.join("htif.rs")) - .expect("Couldn't write htif defines"); - pma.write_to_file(out_path.join("pma.rs")) - .expect("Couldn't write pma defines"); // Setup reruns println!("cargo:rerun-if-changed=build.rs"); @@ -120,6 +90,7 @@ mod build_cm { // Get uarch cfg_if::cfg_if! { if #[cfg(feature = "build_uarch")] { + // requires docker () } else if #[cfg(feature = "copy_uarch")] { let uarch_path = machine_dir_path.join("uarch"); @@ -131,7 +102,9 @@ mod build_cm { } } + // // Build and link emulator + // // build dependencies Command::new("make") @@ -210,11 +183,12 @@ mod build_cm { process::{Command, Stdio}, }; + const VERSION_STRING: &str = "v0.19.0-test2"; + pub fn download(machine_dir_path: &Path) { - // apply git patche for 0.18.1 let patch_file = machine_dir_path.join("add-generated-files.diff"); - download_git_patch(&patch_file, "v0.18.1"); + download_git_patch(&patch_file, VERSION_STRING); apply_git_patch(&patch_file, machine_dir_path); } @@ -282,7 +256,26 @@ mod build_cm { } } -#[allow(dead_code)] +mod feature_checks { + #[cfg(all(feature = "build_uarch", feature = "copy_uarch",))] + compile_error!("Features `build_uarch` and `copy_uarch` are mutually exclusive"); + + #[cfg(all(feature = "build_uarch", feature = "download_uarch"))] + compile_error!("Features `build_uarch` and `download_uarch` are mutually exclusive"); + + #[cfg(all(feature = "copy_uarch", feature = "download_uarch"))] + compile_error!("Features `copy_uarch`, and `download_uarch` are mutually exclusive"); + + #[cfg(not(any( + feature = "copy_uarch", + feature = "download_uarch", + feature = "build_uarch", + feature = "external_cartesi", + )))] + compile_error!("At least one of `build_uarch`, `copy_uarch`, `download_uarch`, and `external_cartesi` must be set"); +} + +#[allow(unused)] fn clean(path: &PathBuf) { // clean build artifacts Command::new("make") diff --git a/machine/rust-bindings/cartesi-machine-sys/src/lib.rs b/machine/rust-bindings/cartesi-machine-sys/src/lib.rs index 133a4417..04af9171 100644 --- a/machine/rust-bindings/cartesi-machine-sys/src/lib.rs +++ b/machine/rust-bindings/cartesi-machine-sys/src/lib.rs @@ -5,5 +5,5 @@ extern crate link_cplusplus; include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -include!(concat!(env!("OUT_DIR"), "/htif.rs")); -include!(concat!(env!("OUT_DIR"), "/pma.rs")); +// include!(concat!(env!("OUT_DIR"), "/htif.rs")); +// include!(concat!(env!("OUT_DIR"), "/pma.rs")); diff --git a/machine/rust-bindings/cartesi-machine/Cargo.toml b/machine/rust-bindings/cartesi-machine/Cargo.toml index ad414c41..ae8286cd 100644 --- a/machine/rust-bindings/cartesi-machine/Cargo.toml +++ b/machine/rust-bindings/cartesi-machine/Cargo.toml @@ -17,5 +17,12 @@ remote_machine = ["cartesi-machine-sys/remote_machine"] [dependencies] cartesi-machine-sys = { path = "../cartesi-machine-sys" } -hex = "0.4.3" -thiserror = "1.0" +base64 = "0.22" +derive_builder = "0.20" +hex = "0.4" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +thiserror = "2.0" + +[dev-dependencies] +tempfile = "3.16" diff --git a/machine/rust-bindings/cartesi-machine/src/config/machine.rs b/machine/rust-bindings/cartesi-machine/src/config/machine.rs new file mode 100644 index 00000000..4b4315c9 --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/config/machine.rs @@ -0,0 +1,566 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct MachineConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub processor: Option, + pub ram: RAMConfig, + #[serde(skip_serializing_if = "Option::is_none")] + pub dtb: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub flash_drive: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub tlb: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub clint: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub plic: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub htif: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub uarch: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cmio: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub virtio: Option, +} + +impl Default for MachineConfig { + fn default() -> Self { + crate::machine::Machine::default_config().expect("failed to get default config") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ProcessorConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub x0: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x1: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x2: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x3: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x4: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x5: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x6: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x7: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x8: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x9: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x10: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x11: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x12: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x13: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x14: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x15: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x16: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x17: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x18: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x19: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x20: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x21: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x22: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x23: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x24: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x25: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x26: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x27: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x28: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x29: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x30: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x31: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f0: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f1: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f2: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f3: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f4: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f5: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f6: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f7: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f8: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f9: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f10: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f11: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f12: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f13: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f14: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f15: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f16: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f17: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f18: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f19: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f20: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f21: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f22: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f23: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f24: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f25: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f26: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f27: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f28: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f29: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f30: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub f31: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub pc: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub fcsr: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mvendorid: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub marchid: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mimpid: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mcycle: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub icycleinstret: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mstatus: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mtvec: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mscratch: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mepc: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mcause: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mtval: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub misa: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mie: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mip: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub medeleg: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mideleg: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mcounteren: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub menvcfg: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub stvec: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub sscratch: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub sepc: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub scause: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub stval: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub satp: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub scounteren: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub senvcfg: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub ilrsc: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub iprv: Option, + #[serde(rename = "iflags_X")] + #[serde(skip_serializing_if = "Option::is_none")] + pub iflags_x: Option, + #[serde(rename = "iflags_Y")] + #[serde(skip_serializing_if = "Option::is_none")] + pub iflags_y: Option, + #[serde(rename = "iflags_H")] + #[serde(skip_serializing_if = "Option::is_none")] + pub iflags_h: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub iunrep: Option, +} + +impl Default for ProcessorConfig { + fn default() -> Self { + MachineConfig::default() + .processor + .expect("`processor` field should not be empty") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct RAMConfig { + pub length: u64, + #[serde(skip_serializing_if = "Option::is_none")] + pub image_filename: Option, +} + +impl Default for RAMConfig { + fn default() -> Self { + MachineConfig::default().ram + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DTBConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub bootargs: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub init: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub entrypoint: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub image_filename: Option, +} + +impl Default for DTBConfig { + fn default() -> Self { + MachineConfig::default() + .dtb + .expect("`dtb` field should not be empty") + } +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct MemoryRangeConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub start: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub length: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub image_filename: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub shared: Option, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct CmioBufferConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub image_filename: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub shared: Option, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct VirtIOHostfwd { + #[serde(skip_serializing_if = "Option::is_none")] + pub is_udp: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub host_ip: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub guest_ip: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub host_port: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub guest_port: Option, +} + +pub type VirtIOHostfwdArray = Vec; + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum VirtIODeviceType { + #[default] + Console, + P9fs, + #[serde(rename = "net-user")] + NetUser, + #[serde(rename = "net-tuntap")] + NetTuntap, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct VirtIODeviceConfig { + pub r#type: VirtIODeviceType, + #[serde(skip_serializing_if = "Option::is_none")] + pub tag: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub host_directory: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub hostfwd: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub iface: Option, +} + +pub type FlashDriveConfigs = Vec; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct TLBConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub image_filename: Option, +} + +impl Default for TLBConfig { + fn default() -> Self { + MachineConfig::default() + .tlb + .expect("`tlb` field should not be empty") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct CLINTConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub mtimecmp: Option, +} + +impl Default for CLINTConfig { + fn default() -> Self { + MachineConfig::default() + .clint + .expect("`clint` field should not be empty") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct PLICConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub girqpend: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub girqsrvd: Option, +} + +impl Default for PLICConfig { + fn default() -> Self { + MachineConfig::default() + .plic + .expect("`plic` field should not be empty") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct HTIFConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub fromhost: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub tohost: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub console_getchar: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub yield_manual: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub yield_automatic: Option, +} + +impl Default for HTIFConfig { + fn default() -> Self { + MachineConfig::default() + .htif + .expect("`htif` field should not be empty") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct UarchProcessorConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub x0: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x1: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x2: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x3: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x4: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x5: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x6: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x7: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x8: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x9: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x10: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x11: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x12: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x13: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x14: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x15: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x16: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x17: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x18: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x19: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x20: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x21: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x22: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x23: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x24: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x25: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x26: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x27: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x28: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x29: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x30: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub x31: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub pc: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cycle: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub halt_flag: Option, +} + +impl Default for UarchProcessorConfig { + fn default() -> Self { + MachineConfig::default() + .uarch + .expect("`uarch` field should not be empty") + .processor + .expect("`uarch.processor` field should not be empty") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct UarchRAMConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub length: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub image_filename: Option, +} + +impl Default for UarchRAMConfig { + fn default() -> Self { + MachineConfig::default() + .uarch + .expect("`uarch` field should not be empty") + .ram + .expect("`uarch.ram` field should not be empty") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct UarchConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub processor: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub ram: Option, +} + +impl Default for UarchConfig { + fn default() -> Self { + MachineConfig::default() + .uarch + .expect("`uarch` field should not be empty") + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct CmioConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub rx_buffer: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub tx_buffer: Option, +} + +impl Default for CmioConfig { + fn default() -> Self { + MachineConfig::default() + .cmio + .expect("`plic` field should not be empty") + } +} + +pub type VirtIOConfigs = Vec; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_default_configs() { + MachineConfig::default(); + ProcessorConfig::default(); + RAMConfig::default(); + DTBConfig::default(); + TLBConfig::default(); + CLINTConfig::default(); + PLICConfig::default(); + HTIFConfig::default(); + UarchProcessorConfig::default(); + UarchRAMConfig::default(); + UarchConfig::default(); + CmioConfig::default(); + } +} diff --git a/machine/rust-bindings/cartesi-machine/src/config/mod.rs b/machine/rust-bindings/cartesi-machine/src/config/mod.rs new file mode 100644 index 00000000..89708d9f --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/config/mod.rs @@ -0,0 +1,5 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +pub mod machine; +pub mod runtime; diff --git a/machine/rust-bindings/cartesi-machine/src/config/runtime.rs b/machine/rust-bindings/cartesi-machine/src/config/runtime.rs new file mode 100644 index 00000000..6f131d4a --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/config/runtime.rs @@ -0,0 +1,32 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct ConcurrencyRuntimeConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub update_merkle_tree: Option, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct HTIFRuntimeConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub no_console_putchar: Option, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct RuntimeConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub concurrency: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub htif: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub skip_root_hash_check: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub skip_root_hash_store: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub skip_version_check: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub soft_yield: Option, +} diff --git a/machine/rust-bindings/cartesi-machine/src/configuration.rs b/machine/rust-bindings/cartesi-machine/src/configuration.rs deleted file mode 100644 index 90e248ec..00000000 --- a/machine/rust-bindings/cartesi-machine/src/configuration.rs +++ /dev/null @@ -1,115 +0,0 @@ -// (c) Cartesi and individual authors (see AUTHORS) -// SPDX-License-Identifier: Apache-2.0 (see LICENSE) - -pub type MemoryRangeConfig = cartesi_machine_sys::cm_memory_range_config; -pub type CmIoConfig = cartesi_machine_sys::cm_cmio_config; -pub type CmIoBufferConfig = cartesi_machine_sys::cm_cmio_buffer_config; -pub type HtifConfig = cartesi_machine_sys::cm_htif_config; - -pub type MachineConfig = cartesi_machine_sys::cm_machine_config; - -#[derive(Debug)] -pub struct MachineConfigRef { - config: *const MachineConfig, -} - -impl Drop for MachineConfigRef { - fn drop(&mut self) { - unsafe { - cartesi_machine_sys::cm_delete_machine_config(self.config); - }; - } -} - -impl Default for MachineConfigRef { - fn default() -> Self { - let mut error_collector = crate::errors::ErrorCollector::new(); - let mut config = std::ptr::null(); - - let result = unsafe { - cartesi_machine_sys::cm_get_default_config(&mut config, error_collector.as_mut_ptr()) - }; - error_collector - .collect(result) - .expect("cm_get_default_config should never fail"); - - Self { config } - } -} - -impl MachineConfigRef { - pub fn try_new( - machine: &crate::Machine, - ) -> Result { - let mut error_collector = crate::errors::ErrorCollector::new(); - let mut config = std::ptr::null(); - - let result = unsafe { - cartesi_machine_sys::cm_get_initial_config( - machine.machine, - &mut config, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; - - Ok(Self { config }) - } - - pub fn inner(&self) -> &MachineConfig { - unsafe { self.config.as_ref().unwrap() } - } -} - -type CmRuntimeConfig = cartesi_machine_sys::cm_machine_runtime_config; - -#[derive(Debug, Clone)] -pub struct RuntimeConfig { - pub values: CmRuntimeConfig, -} - -impl Default for RuntimeConfig { - fn default() -> Self { - Self { - values: CmRuntimeConfig { - concurrency: cartesi_machine_sys::cm_concurrency_runtime_config { - update_merkle_tree: 0, - }, - htif: cartesi_machine_sys::cm_htif_runtime_config { - no_console_putchar: true, - }, - skip_root_hash_check: false, - skip_version_check: false, - soft_yield: false, - skip_root_hash_store: false, - }, - } - } -} - -impl RuntimeConfig { - pub fn concurrency(mut self, update_merkle_tree: u64) -> Self { - self.values.concurrency.update_merkle_tree = update_merkle_tree; - self - } - - pub fn no_console_putchar(mut self, no_console_putchar: bool) -> Self { - self.values.htif.no_console_putchar = no_console_putchar; - self - } - - pub fn skip_root_hash_check(mut self, skip_root_hash_check: bool) -> Self { - self.values.skip_root_hash_check = skip_root_hash_check; - self - } - - pub fn skip_version_check(mut self, skip_version_check: bool) -> Self { - self.values.skip_version_check = skip_version_check; - self - } - - pub fn soft_yield(mut self, soft_yield: bool) -> Self { - self.values.soft_yield = soft_yield; - self - } -} diff --git a/machine/rust-bindings/cartesi-machine/src/constants.rs b/machine/rust-bindings/cartesi-machine/src/constants.rs index 859e56cc..a835c100 100644 --- a/machine/rust-bindings/cartesi-machine/src/constants.rs +++ b/machine/rust-bindings/cartesi-machine/src/constants.rs @@ -3,132 +3,112 @@ //! Constants definitions from Cartesi Machine -/// +pub mod machine { + use cartesi_machine_sys::*; + pub const CYCLE_MAX: u64 = CM_MCYCLE_MAX as u64; + pub const HASH_SIZE: u32 = CM_HASH_SIZE; + pub const TREE_LOG2_WORD_SIZE: u32 = CM_TREE_LOG2_WORD_SIZE; + pub const TREE_LOG2_PAGE_SIZE: u32 = CM_TREE_LOG2_PAGE_SIZE; + pub const TREE_LOG2_ROOT_SIZE: u32 = CM_TREE_LOG2_ROOT_SIZE; +} + +pub mod pma { + use cartesi_machine_sys::*; + pub const RX_START: u64 = CM_PMA_CMIO_RX_BUFFER_START as u64; + pub const RX_LOG2_SIZE: u64 = CM_PMA_CMIO_RX_BUFFER_LOG2_SIZE as u64; + pub const TX_START: u64 = CM_PMA_CMIO_TX_BUFFER_START as u64; + pub const TX_LOG2_SIZE: u64 = CM_PMA_CMIO_TX_BUFFER_LOG2_SIZE as u64; + pub const RAM_START: u64 = CM_PMA_RAM_START as u64; +} + pub mod break_reason { use cartesi_machine_sys::*; - pub const FAILED: u32 = CM_BREAK_REASON_CM_BREAK_REASON_FAILED; - pub const HALTED: u32 = CM_BREAK_REASON_CM_BREAK_REASON_HALTED; - pub const YIELDED_MANUALLY: u32 = CM_BREAK_REASON_CM_BREAK_REASON_YIELDED_MANUALLY; - pub const YIELDED_AUTOMATICALLY: u32 = CM_BREAK_REASON_CM_BREAK_REASON_YIELDED_AUTOMATICALLY; - pub const YIELDED_SOFTLY: u32 = CM_BREAK_REASON_CM_BREAK_REASON_YIELDED_SOFTLY; - pub const REACHED_TARGET_MCYCLE: u32 = CM_BREAK_REASON_CM_BREAK_REASON_REACHED_TARGET_MCYCLE; + pub const FAILED: u32 = CM_BREAK_REASON_FAILED; + pub const HALTED: u32 = CM_BREAK_REASON_HALTED; + pub const YIELDED_MANUALLY: u32 = CM_BREAK_REASON_YIELDED_MANUALLY; + pub const YIELDED_AUTOMATICALLY: u32 = CM_BREAK_REASON_YIELDED_AUTOMATICALLY; + pub const YIELDED_SOFTLY: u32 = CM_BREAK_REASON_YIELDED_SOFTLY; + pub const REACHED_TARGET_MCYCLE: u32 = CM_BREAK_REASON_REACHED_TARGET_MCYCLE; } -/// pub mod uarch_break_reason { use cartesi_machine_sys::*; - pub const REACHED_TARGET_CYCLE: u32 = - CM_UARCH_BREAK_REASON_CM_UARCH_BREAK_REASON_REACHED_TARGET_CYCLE; - pub const UARCH_HALTED: u32 = CM_UARCH_BREAK_REASON_CM_UARCH_BREAK_REASON_UARCH_HALTED; + pub const REACHED_TARGET_CYCLE: u32 = CM_UARCH_BREAK_REASON_REACHED_TARGET_CYCLE; + pub const UARCH_HALTED: u32 = CM_UARCH_BREAK_REASON_UARCH_HALTED; } -/// -pub mod htif { - pub mod masks { - use cartesi_machine_sys::*; - pub const DEVICE_SHIFT: u32 = HTIF_DEV_SHIFT_DEF; - pub const COMMAND_SHIFT: u32 = HTIF_CMD_SHIFT_DEF; - pub const DATA_SHIFT: u32 = HTIF_DATA_SHIFT_DEF; - pub const DEVICE_MASK: u64 = HTIF_DEV_MASK_DEF as u64; - pub const COMMAND_MASK: u64 = HTIF_CMD_MASK_DEF as u64; - pub const DATA_MASK: u64 = HTIF_DATA_MASK_DEF as u64; - } - - /// HTIF devices - pub mod devices { - use cartesi_machine_sys::*; - pub const HALT: u32 = HTIF_DEV_HALT_DEF; - pub const CONSOLE: u32 = HTIF_DEV_CONSOLE_DEF; - pub const YIELD: u32 = HTIF_DEV_YIELD_DEF; - } +pub mod access_log_type { + use cartesi_machine_sys::*; + pub const ANNOTATIONS: u32 = CM_ACCESS_LOG_TYPE_ANNOTATIONS; + pub const LARGE_DATA: u32 = CM_ACCESS_LOG_TYPE_LARGE_DATA; +} - /// HTIF commands +pub mod cmio { + /// CMIO commands pub mod commands { use cartesi_machine_sys::*; - pub const HALT_HALT: u32 = HTIF_HALT_CMD_HALT_DEF; - pub const CONSOLE_GETCHAR: u32 = HTIF_CONSOLE_CMD_GETCHAR_DEF; - pub const CONSOLE_PUTCHAR: u32 = HTIF_CONSOLE_CMD_PUTCHAR_DEF; - pub const YIELD_AUTOMATIC: u32 = HTIF_YIELD_CMD_AUTOMATIC_DEF; - pub const YIELD_MANUAL: u32 = HTIF_YIELD_CMD_MANUAL_DEF; + pub const YIELD_AUTOMATIC: u8 = CM_CMIO_YIELD_COMMAND_AUTOMATIC as u8; + pub const YIELD_MANUAL: u8 = CM_CMIO_YIELD_COMMAND_MANUAL as u8; } - /// HTIF request + /// CMIO request pub mod tohost { pub mod automatic { use cartesi_machine_sys::*; - pub const PROGRESS: u32 = HTIF_YIELD_AUTOMATIC_REASON_PROGRESS_DEF; - pub const TX_OUTPUT: u32 = HTIF_YIELD_AUTOMATIC_REASON_TX_OUTPUT_DEF; - pub const TX_REPORT: u32 = HTIF_YIELD_AUTOMATIC_REASON_TX_REPORT_DEF; + pub const PROGRESS: u16 = CM_CMIO_YIELD_AUTOMATIC_REASON_PROGRESS as u16; + pub const TX_OUTPUT: u16 = CM_CMIO_YIELD_AUTOMATIC_REASON_TX_OUTPUT as u16; + pub const TX_REPORT: u16 = CM_CMIO_YIELD_AUTOMATIC_REASON_TX_REPORT as u16; } pub mod manual { use cartesi_machine_sys::*; - pub const RX_ACCEPTED: u32 = HTIF_YIELD_MANUAL_REASON_RX_ACCEPTED_DEF; - pub const RX_REJECTED: u32 = HTIF_YIELD_MANUAL_REASON_RX_REJECTED_DEF; - pub const TX_EXCEPTION: u32 = HTIF_YIELD_MANUAL_REASON_TX_EXCEPTION_DEF; + pub const RX_ACCEPTED: u16 = CM_CMIO_YIELD_MANUAL_REASON_RX_ACCEPTED as u16; + pub const RX_REJECTED: u16 = CM_CMIO_YIELD_MANUAL_REASON_RX_REJECTED as u16; + pub const TX_EXCEPTION: u16 = CM_CMIO_YIELD_MANUAL_REASON_TX_EXCEPTION as u16; } } - /// HTIF reply + /// CMIO response pub mod fromhost { use cartesi_machine_sys::*; - pub const ADVANCE_STATE: u16 = HTIF_YIELD_REASON_ADVANCE_STATE_DEF as u16; - pub const INSPECT_STATE: u16 = HTIF_YIELD_REASON_INSPECT_STATE_DEF as u16; + pub const ADVANCE_STATE: u16 = CM_CMIO_YIELD_REASON_ADVANCE_STATE as u16; + pub const INSPECT_STATE: u16 = CM_CMIO_YIELD_REASON_INSPECT_STATE as u16; } } -/// -pub mod pma { - use cartesi_machine_sys::*; - pub const CMIO_RX_BUFFER_START: u64 = PMA_CMIO_RX_BUFFER_START_DEF as u64; - pub const CMIO_RX_BUFFER_LOG2_SIZE: u64 = PMA_CMIO_RX_BUFFER_LOG2_SIZE_DEF as u64; - pub const CMIO_TX_BUFFER_START: u64 = PMA_CMIO_TX_BUFFER_START_DEF as u64; - pub const CMIO_TX_BUFFER_LOG2_SIZE: u64 = PMA_CMIO_TX_BUFFER_LOG2_SIZE_DEF as u64; -} - -pub mod error { +pub mod error_code { use cartesi_machine_sys::*; - pub const OK: u32 = CM_ERROR_CM_ERROR_OK; + pub const OK: i32 = CM_ERROR_OK; // Logic errors - pub const INVALID_ARGUMENT: u32 = CM_ERROR_CM_ERROR_INVALID_ARGUMENT; - pub const DOMAIN_ERROR: u32 = CM_ERROR_CM_ERROR_DOMAIN_ERROR; - pub const LENGTH_ERROR: u32 = CM_ERROR_CM_ERROR_LENGTH_ERROR; - pub const OUT_OF_RANGE: u32 = CM_ERROR_CM_ERROR_OUT_OF_RANGE; - pub const LOGIC_ERROR: u32 = CM_ERROR_CM_ERROR_LOGIC_ERROR; - pub const LOGIC_ERROR_END: u32 = CM_ERROR_CM_LOGIC_ERROR_END; - - // Bad optional access error - pub const BAD_OPTIONAL_ACCESS: u32 = CM_ERROR_CM_ERROR_BAD_OPTIONAL_ACCESS; + pub const INVALID_ARGUMENT: i32 = CM_ERROR_INVALID_ARGUMENT; + pub const DOMAIN_ERROR: i32 = CM_ERROR_DOMAIN_ERROR; + pub const LENGTH_ERROR: i32 = CM_ERROR_LENGTH_ERROR; + pub const OUT_OF_RANGE: i32 = CM_ERROR_OUT_OF_RANGE; + pub const LOGIC_ERROR: i32 = CM_ERROR_LOGIC_ERROR; // Runtime errors - pub const RUNTIME_ERROR: u32 = CM_ERROR_CM_ERROR_RUNTIME_ERROR; - pub const RANGE_ERROR: u32 = CM_ERROR_CM_ERROR_RANGE_ERROR; - pub const OVERFLOW_ERROR: u32 = CM_ERROR_CM_ERROR_OVERFLOW_ERROR; - pub const UNDERFLOW_ERROR: u32 = CM_ERROR_CM_ERROR_UNDERFLOW_ERROR; - pub const REGEX_ERROR: u32 = CM_ERROR_CM_ERROR_REGEX_ERROR; - pub const SYSTEM_IOS_BASE_FAILURE: u32 = CM_ERROR_CM_ERROR_SYSTEM_IOS_BASE_FAILURE; - pub const FILESYSTEM_ERROR: u32 = CM_ERROR_CM_ERROR_FILESYSTEM_ERROR; - pub const ATOMIC_TX_ERROR: u32 = CM_ERROR_CM_ERROR_ATOMIC_TX_ERROR; - pub const NONEXISTING_LOCAL_TIME: u32 = CM_ERROR_CM_ERROR_NONEXISTING_LOCAL_TIME; - pub const AMBIGOUS_LOCAL_TIME: u32 = CM_ERROR_CM_ERROR_AMBIGUOUS_LOCAL_TIME; - pub const FORMAT_ERROR: u32 = CM_ERROR_CM_ERROR_FORMAT_ERROR; - pub const RUNTIME_ERROR_END: u32 = CM_ERROR_CM_RUNTIME_ERROR_END; + pub const RUNTIME_ERROR: i32 = CM_ERROR_RUNTIME_ERROR; + pub const RANGE_ERROR: i32 = CM_ERROR_RANGE_ERROR; + pub const OVERFLOW_ERROR: i32 = CM_ERROR_OVERFLOW_ERROR; + pub const UNDERFLOW_ERROR: i32 = CM_ERROR_UNDERFLOW_ERROR; + pub const REGEX_ERROR: i32 = CM_ERROR_REGEX_ERROR; + pub const SYSTEM_ERROR: i32 = CM_ERROR_SYSTEM_ERROR; // Other errors - pub const BAD_TYPEID: u32 = CM_ERROR_CM_ERROR_BAD_TYPEID; - pub const BAD_CAST: u32 = CM_ERROR_CM_ERROR_BAD_CAST; - pub const BAD_ANY_CAST: u32 = CM_ERROR_CM_ERROR_BAD_ANY_CAST; - pub const BAD_WEAK_PTR: u32 = CM_ERROR_CM_ERROR_BAD_WEAK_PTR; - pub const BAD_FUNCTION_CALL: u32 = CM_ERROR_CM_ERROR_BAD_FUNCTION_CALL; - pub const BAD_ALLOC: u32 = CM_ERROR_CM_ERROR_BAD_ALLOC; - pub const BAD_ARRAY_NEW_LENGTH: u32 = CM_ERROR_CM_ERROR_BAD_ARRAY_NEW_LENGTH; - pub const BAD_EXCEPTION: u32 = CM_ERROR_CM_ERROR_BAD_EXCEPTION; - pub const BAD_VARIANT_ACCESS: u32 = CM_ERROR_CM_ERROR_BAD_VARIANT_ACCESS; - pub const EXCEPTION: u32 = CM_ERROR_CM_ERROR_EXCEPTION; - pub const OTHER_ERROR_END: u32 = CM_ERROR_CM_OTHER_ERROR_END; + pub const BAD_TYPEID: i32 = CM_ERROR_BAD_TYPEID; + pub const BAD_CAST: i32 = CM_ERROR_BAD_CAST; + pub const BAD_ANY_CAST: i32 = CM_ERROR_BAD_ANY_CAST; + pub const BAD_OPTIONAL_ACCESS: i32 = CM_ERROR_BAD_OPTIONAL_ACCESS; + pub const BAD_WEAK_PTR: i32 = CM_ERROR_BAD_WEAK_PTR; + pub const BAD_FUNCTION_CALL: i32 = CM_ERROR_BAD_FUNCTION_CALL; + pub const BAD_ALLOC: i32 = CM_ERROR_BAD_ALLOC; + pub const BAD_ARRAY_NEW_LENGTH: i32 = CM_ERROR_BAD_ARRAY_NEW_LENGTH; + pub const BAD_EXCEPTION: i32 = CM_ERROR_BAD_EXCEPTION; + pub const BAD_VARIANT_ACCESS: i32 = CM_ERROR_BAD_VARIANT_ACCESS; + pub const EXCEPTION: i32 = CM_ERROR_EXCEPTION; // C API Errors - pub const UNKNOWN: u32 = CM_ERROR_CM_ERROR_UNKNOWN; + pub const UNKNOWN: i32 = CM_ERROR_UNKNOWN; } diff --git a/machine/rust-bindings/cartesi-machine/src/error.rs b/machine/rust-bindings/cartesi-machine/src/error.rs new file mode 100644 index 00000000..6438b6bb --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/error.rs @@ -0,0 +1,21 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +//! Error handling for the machine emulator + +use std::fmt::Display; + +pub type MachineResult = Result; + +/// Error returned from machine emulator C API +#[derive(Debug, Clone, thiserror::Error)] +pub struct MachineError { + pub code: i32, + pub message: String, +} + +impl Display for MachineError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Cartesi Machine error {}: {}", self.code, self.message) + } +} diff --git a/machine/rust-bindings/cartesi-machine/src/errors.rs b/machine/rust-bindings/cartesi-machine/src/errors.rs deleted file mode 100644 index c816aa94..00000000 --- a/machine/rust-bindings/cartesi-machine/src/errors.rs +++ /dev/null @@ -1,58 +0,0 @@ -// (c) Cartesi and individual authors (see AUTHORS) -// SPDX-License-Identifier: Apache-2.0 (see LICENSE) - -//! Error handling for the machine emulator - -use crate::utils::from_cstr; -use std::{ffi::c_char, fmt::Display, mem::MaybeUninit}; - -/// Error returned from machine emulator C API -#[derive(Debug, Clone, thiserror::Error)] -pub struct MachineError { - code: i32, - message: Option, -} - -impl Display for MachineError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Error with code {}: {}", - self.code as u8, - self.message.clone().unwrap_or_default() - ) - } -} - -/// Collects an error and cleans the memory. It's used to avoid accidental memory leaks when -/// handling errors using the ownership of [ErrorCollector], the inability to clone it and the -/// [cm_delete_cstring] function. -pub(crate) struct ErrorCollector { - ptr: MaybeUninit<*mut c_char>, -} - -impl ErrorCollector { - /// Creates a new error collector - pub fn new() -> Self { - Self { - ptr: MaybeUninit::<*mut c_char>::uninit(), - } - } - - /// Gets the pointer to the error message - pub fn as_mut_ptr(&mut self) -> *mut *mut c_char { - self.ptr.as_mut_ptr() - } - - /// Collect error from C API - pub fn collect(self, code: i32) -> Result<(), MachineError> { - if code == cartesi_machine_sys::CM_ERROR_CM_ERROR_OK as i32 { - Ok(()) - } else { - let message = unsafe { from_cstr(*self.ptr.as_ptr()) }; - unsafe { cartesi_machine_sys::cm_delete_cstring(*self.ptr.as_ptr()) }; - - Err(MachineError { code, message }) - } - } -} diff --git a/machine/rust-bindings/cartesi-machine/src/hash.rs b/machine/rust-bindings/cartesi-machine/src/hash.rs deleted file mode 100644 index 15aff8d8..00000000 --- a/machine/rust-bindings/cartesi-machine/src/hash.rs +++ /dev/null @@ -1,34 +0,0 @@ -// (c) Cartesi and individual authors (see AUTHORS) -// SPDX-License-Identifier: Apache-2.0 (see LICENSE) - -//! Defines the [struct@Hash] type. - -use std::fmt::Display; - -type Digest = [u8; 32]; - -/// Digest generated by a hash function. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Hash(Digest); - -impl Display for Hash { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "0x{}", hex::encode(self.0)) - } -} - -impl Hash { - pub fn as_ptr(&self) -> *const Digest { - &self.0 - } - - /// Create a new hash from a byte array. - pub fn new(hash: Digest) -> Self { - Self(hash) - } - - /// Get the byte array representation of this hash. - pub fn as_bytes(&self) -> &[u8] { - &self.0 - } -} diff --git a/machine/rust-bindings/cartesi-machine/src/lib.rs b/machine/rust-bindings/cartesi-machine/src/lib.rs index 39848d0a..06c0222a 100644 --- a/machine/rust-bindings/cartesi-machine/src/lib.rs +++ b/machine/rust-bindings/cartesi-machine/src/lib.rs @@ -3,20 +3,12 @@ #![doc = include_str!("../README.md")] -pub mod configuration; -pub mod errors; - -pub mod hash; +pub mod config; +pub mod constants; +pub mod error; pub mod machine; +pub mod types; -// TODO: review -pub mod log; -pub mod proof; - -mod constants; -mod utils; - -pub use constants::*; pub use machine::Machine; // Reexport inner cartesi-machine-sys diff --git a/machine/rust-bindings/cartesi-machine/src/log.rs b/machine/rust-bindings/cartesi-machine/src/log.rs deleted file mode 100644 index 60d895a4..00000000 --- a/machine/rust-bindings/cartesi-machine/src/log.rs +++ /dev/null @@ -1,184 +0,0 @@ -//! Logging utilities for Cartesi Machine. - -use crate::{hash::Hash, utils}; - -/// Type of state access -#[derive(Debug, PartialEq, Eq)] -pub enum AccessType { - /// Read operation - Read = 0, - /// Write operation - Write, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] -/// Type of access log -pub struct AccessLogType { - /// Includes proofs - pub proofs: bool, - /// Includes annotations - pub annotations: bool, - /// Includes data bigger than 8 bytes - pub large_data: bool, -} - -impl From for cartesi_machine_sys::cm_access_log_type { - fn from(log_type: AccessLogType) -> Self { - unsafe { std::mem::transmute(log_type) } - } -} - -impl From for AccessLogType { - fn from(log_type: cartesi_machine_sys::cm_access_log_type) -> Self { - unsafe { std::mem::transmute(log_type) } - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] -/// Bracket type -pub enum BracketType { - /// Start of scope - Begin = 0, - /// End of scope - End, -} - -/// Bracket Note -pub struct BracketNote<'a> { - ptr: *const cartesi_machine_sys::cm_bracket_note, - phantom: std::marker::PhantomData<&'a ()>, -} - -impl<'a> BracketNote<'a> { - fn new(ptr: *const cartesi_machine_sys::cm_bracket_note) -> Self { - Self { - ptr, - phantom: std::marker::PhantomData, - } - } - - pub fn kind(&self) -> BracketType { - unsafe { std::mem::transmute((*self.ptr).type_) } - } - - pub fn r#where(&self) -> u64 { - unsafe { (*self.ptr).where_ } - } - - pub fn text(&self) -> String { - unsafe { utils::from_cstr((*self.ptr).text) }.unwrap() - } -} - -/// Record of an access to the machine state -pub struct Access<'a> { - ptr: *const cartesi_machine_sys::cm_access, - phantom: std::marker::PhantomData<&'a ()>, -} - -impl<'a> Access<'a> { - fn new(ptr: *const cartesi_machine_sys::cm_access) -> Self { - Self { - ptr, - phantom: std::marker::PhantomData, - } - } - - /// Type of access - pub fn access_type(&self) -> AccessType { - unsafe { std::mem::transmute((*self.ptr).type_ as u8) } - } - - /// Address of access - pub fn address(&self) -> u64 { - unsafe { (*self.ptr).address } - } - - /// Log2 of size of access - pub fn log2_size(&self) -> i32 { - unsafe { (*self.ptr).log2_size } - } - - /// Hash of data before access - pub fn read_hash(&self) -> Hash { - Hash::new(unsafe { (*self.ptr).read_hash }) - } - - /// Data before access - pub fn read_data(&self) -> &[u8] { - unsafe { std::slice::from_raw_parts((*self.ptr).read_data, (*self.ptr).read_data_size) } - } - - /// Hash of data after access (if writing) - pub fn written_hash(&self) -> Hash { - Hash::new(unsafe { (*self.ptr).written_hash }) - } - - /// Data after access (if writing) - pub fn written_data(&self) -> &[u8] { - unsafe { - std::slice::from_raw_parts((*self.ptr).written_data, (*self.ptr).written_data_size) - } - } - - /// Sibling hashes towards root - pub fn sibling_hashes(&self) -> Vec { - let sibling_hashes = unsafe { *(*self.ptr).sibling_hashes }; - let sibling_hashes = - unsafe { std::slice::from_raw_parts(sibling_hashes.entry, sibling_hashes.count) }; - - sibling_hashes.iter().map(|hash| Hash::new(*hash)).collect() - } -} - -/// Log of state accesses -pub struct AccessLog(*mut cartesi_machine_sys::cm_access_log); - -impl Drop for AccessLog { - fn drop(&mut self) { - unsafe { cartesi_machine_sys::cm_delete_access_log(self.0) }; - } -} - -impl AccessLog { - pub(crate) fn new(ptr: *mut cartesi_machine_sys::cm_access_log) -> Self { - Self(ptr) - } - - pub(crate) fn as_ptr(&self) -> &cartesi_machine_sys::cm_access_log { - unsafe { &*self.0 } - } - - pub fn accesses(&self) -> Vec { - let accesses = unsafe { (*self.0).accesses }; - let accesses = unsafe { std::slice::from_raw_parts(accesses.entry, accesses.count) }; - - accesses.iter().map(|access| Access::new(access)).collect() - } - - pub fn brackets(&self) -> Vec { - let brackets = unsafe { (*self.0).brackets }; - let brackets = unsafe { std::slice::from_raw_parts(brackets.entry, brackets.count) }; - - brackets - .iter() - .map(|bracket| BracketNote::new(bracket)) - .collect() - } - - pub fn notes(&self) -> Vec { - let notes = unsafe { (*self.0).notes }; - let notes = unsafe { std::slice::from_raw_parts(notes.entry, notes.count) }; - - notes - .iter() - .map(|note| utils::from_cstr(*note).unwrap()) - .collect() - } - - pub fn log_type(&self) -> AccessLogType { - unsafe { std::mem::transmute((*self.0).log_type) } - } -} diff --git a/machine/rust-bindings/cartesi-machine/src/machine.rs b/machine/rust-bindings/cartesi-machine/src/machine.rs index ee72c391..49a3abe4 100644 --- a/machine/rust-bindings/cartesi-machine/src/machine.rs +++ b/machine/rust-bindings/cartesi-machine/src/machine.rs @@ -1,772 +1,955 @@ -use std::path::Path; - -use crate::configuration::*; -use crate::errors::*; -use crate::hash; -use crate::log; -use crate::proof; +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use std::{ + ffi::{c_char, CStr, CString}, + path::Path, + ptr, +}; + +use crate::{ + config::{self, machine::MachineConfig, runtime::RuntimeConfig}, + constants, + error::{MachineError, MachineResult as Result}, + types::{ + access_proof::AccessLog, + cmio::{CmioRequest, CmioResponseReason}, + memory_proof::Proof, + memory_range::MemoryRangeDescriptions, + BreakReason, Hash, LogType, Register, UArchBreakReason, + }, +}; /// Machine instance handle pub struct Machine { pub machine: *mut cartesi_machine_sys::cm_machine, - pub runtime_config: RuntimeConfig, } impl Drop for Machine { fn drop(&mut self) { unsafe { - cartesi_machine_sys::cm_delete_machine(self.machine); + cartesi_machine_sys::cm_delete(self.machine); } } } -impl Machine { - /// Create machine instance from previously serialized directory - pub fn load(path: &Path, runtime_config: RuntimeConfig) -> Result { - let mut machine = std::ptr::null_mut(); - { - let mut error_collector = ErrorCollector::new(); - let path = { - let p = path.to_str().unwrap(); - std::ffi::CString::new(p).unwrap() - }; - - let result = unsafe { - cartesi_machine_sys::cm_load_machine( - path.as_ptr(), - &runtime_config.values, - &mut machine, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; +macro_rules! check_err { + ($err_code:expr) => { + if $err_code != constants::error_code::OK { + Err(Machine::last_error($err_code)) + } else { + Ok(()) } + }; +} - let mut initial_config_ptr = std::ptr::null(); - { - let mut error_collector = ErrorCollector::new(); - - let result = unsafe { - cartesi_machine_sys::cm_get_initial_config( - machine, - &mut initial_config_ptr, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; - } +macro_rules! serialize_to_json { + ($src:expr) => { + CString::new(serde_json::to_string($src).expect("failed serializing to json")) + .expect("CString::new failed") + }; +} - let machine = Machine { - machine, - runtime_config, +macro_rules! parse_json_from_cstring { + ($src:expr) => {{ + let cstr = unsafe { CStr::from_ptr($src) }; + let json = cstr.to_string_lossy(); + serde_json::from_str(&json).expect("could not parse json") + }}; +} + +impl Machine { + // ----------------------------------------------------------------------------- + // API functions + // ----------------------------------------------------------------------------- + + /// Returns the default machine config. + pub fn default_config() -> Result { + let mut config_ptr: *const c_char = ptr::null(); + let err_code = + unsafe { cartesi_machine_sys::cm_get_default_config(ptr::null(), &mut config_ptr) }; + check_err!(err_code)?; + + let config = parse_json_from_cstring!(config_ptr); + + Ok(config) + } + + /// Gets the address of any x, f, or control state register. + pub fn reg_address(reg: Register) -> Result { + let mut val: u64 = 0; + let err_code = + unsafe { cartesi_machine_sys::cm_get_reg_address(ptr::null(), reg, &mut val) }; + check_err!(err_code)?; + Ok(val) + } + + // ----------------------------------------------------------------------------- + // Machine API functions + // ----------------------------------------------------------------------------- + + /// Creates a new machine instance from configuration. + pub fn create(config: &MachineConfig, runtime_config: &RuntimeConfig) -> Result { + let config_json = serialize_to_json!(&config); + let runtime_config_json = serialize_to_json!(&runtime_config); + + let mut machine: *mut cartesi_machine_sys::cm_machine = ptr::null_mut(); + let err_code = unsafe { + cartesi_machine_sys::cm_create_new( + config_json.as_ptr(), + runtime_config_json.as_ptr(), + &mut machine, + ) }; + check_err!(err_code)?; - Ok(machine) + Ok(Self { machine }) } - /// Serialize entire state to directory - pub fn store(&self, path: &Path) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + /// Loads a new machine instance from a previously stored directory. + pub fn load(dir: &Path, runtime_config: &RuntimeConfig) -> Result { + let dir_cstr = path_to_cstring(dir); + let runtime_config_json = serialize_to_json!(&runtime_config); - let path = { - let p = path.to_str().unwrap(); - std::ffi::CString::new(p).unwrap() + let mut machine: *mut cartesi_machine_sys::cm_machine = ptr::null_mut(); + let err_code = unsafe { + cartesi_machine_sys::cm_load_new( + dir_cstr.as_ptr(), + runtime_config_json.as_ptr(), + &mut machine, + ) }; + check_err!(err_code)?; - let result = unsafe { - cartesi_machine_sys::cm_store(self.machine, path.as_ptr(), error_collector.as_mut_ptr()) - }; - error_collector.collect(result)?; + Ok(Self { machine }) + } + + /// Stores a machine instance to a directory, serializing its entire state. + pub fn store(&mut self, dir: &Path) -> Result<()> { + // CM_API cm_error cm_store(const cm_machine *m, const char *dir); + // todo!() + let dir_cstr = path_to_cstring(dir); + let err_code = unsafe { cartesi_machine_sys::cm_store(self.machine, dir_cstr.as_ptr()) }; + check_err!(err_code)?; Ok(()) } - /// Runs the machine until mcycle reaches mcycle_end or the machine halts. - pub fn run(&mut self, mcycle_end: u64) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut break_reason = 0; - - let result = unsafe { - cartesi_machine_sys::cm_machine_run( - self.machine, - mcycle_end, - &mut break_reason, - error_collector.as_mut_ptr(), - ) + /// Changes the machine runtime configuration. + pub fn set_runtime_config(&mut self, runtime_config: &RuntimeConfig) -> Result<()> { + let runtime_config_json = serialize_to_json!(&runtime_config); + let err_code = unsafe { + cartesi_machine_sys::cm_set_runtime_config(self.machine, runtime_config_json.as_ptr()) }; + check_err!(err_code)?; - error_collector.collect(result)?; + Ok(()) + } - Ok(break_reason) + /// Gets the machine runtime config. + pub fn runtime_config(&mut self) -> Result { + let mut rc_ptr: *const c_char = ptr::null(); + let err_code = + unsafe { cartesi_machine_sys::cm_get_runtime_config(self.machine, &mut rc_ptr) }; + check_err!(err_code)?; + + let runtime_config = parse_json_from_cstring!(rc_ptr); + + Ok(runtime_config) } - /// Runs the machine until ucycle reaches ucycle_end or the machine halts. - pub fn run_uarch(&mut self, ucycle_end: u64) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut break_reason = 0; + /// Replaces a memory range. + pub fn replace_memory_range( + &mut self, + start: u64, + length: u64, + shared: bool, + image_path: Option<&Path>, + ) -> Result<()> { + let image_cstr = match image_path { + Some(path) => path_to_cstring(path), + None => CString::new("").unwrap(), + }; + + let image_ptr = if image_path.is_some() { + image_cstr.as_ptr() + } else { + ptr::null() + }; - let result = unsafe { - cartesi_machine_sys::cm_machine_run_uarch( + let err_code = unsafe { + cartesi_machine_sys::cm_replace_memory_range( self.machine, - ucycle_end, - &mut break_reason, - error_collector.as_mut_ptr(), + start, + length, + shared, + image_ptr, ) }; + check_err!(err_code)?; - error_collector.collect(result)?; - Ok(break_reason) + Ok(()) } - /// Write a CMIO response - pub fn send_cmio_response(&mut self, reason: u16, data: &[u8]) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + /// Returns the machine config used to initialize the machine. + pub fn initial_config(&mut self) -> Result { + let mut config_ptr: *const c_char = ptr::null(); + let err_code = + unsafe { cartesi_machine_sys::cm_get_initial_config(self.machine, &mut config_ptr) }; + check_err!(err_code)?; - let result = unsafe { - cartesi_machine_sys::cm_send_cmio_response( - self.machine, - reason, - data.as_ptr(), - data.len(), - error_collector.as_mut_ptr(), - ) - }; + let config = parse_json_from_cstring!(config_ptr); + + Ok(config) + } - error_collector.collect(result)?; + /// Returns a list with all memory ranges in the machine. + pub fn memory_ranges(&mut self) -> Result { + let mut ranges_ptr: *const c_char = ptr::null(); + let err_code = + unsafe { cartesi_machine_sys::cm_get_memory_ranges(self.machine, &mut ranges_ptr) }; + check_err!(err_code)?; - Ok(()) + let ranges = parse_json_from_cstring!(ranges_ptr); + + Ok(ranges) } - /// Write a CMIO response logging all accesses to the state. - pub fn log_send_cmio_response( - &mut self, - reason: u16, - data: &[u8], - log_type: log::AccessLogType, - one_based: bool, - ) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut access_log = std::ptr::null_mut(); + /// Obtains the root hash of the Merkle tree. + pub fn root_hash(&mut self) -> Result { + let mut hash = Hash::default(); + let err_code = unsafe { cartesi_machine_sys::cm_get_root_hash(self.machine, &mut hash) }; + check_err!(err_code)?; - let result = unsafe { - cartesi_machine_sys::cm_log_send_cmio_response( + Ok(hash) + } + + /// Obtains the proof for a node in the machine state Merkle tree. + pub fn proof(&mut self, address: u64, log2_size: u32) -> Result { + let mut proof_ptr: *const c_char = ptr::null(); + let err_code = unsafe { + cartesi_machine_sys::cm_get_proof( self.machine, - reason, - data.as_ptr(), - data.len(), - log_type.into(), - one_based, - &mut access_log, - error_collector.as_mut_ptr(), + address, + log2_size as i32, + &mut proof_ptr, ) }; + check_err!(err_code)?; - error_collector.collect(result)?; + let proof = parse_json_from_cstring!(proof_ptr); - Ok(log::AccessLog::new(access_log)) + Ok(proof) } - /// Runs the machine for one micro cycle logging all accesses to the state. - pub fn log_uarch_step( - &mut self, - log_type: log::AccessLogType, - one_based: bool, - ) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut access_log = std::ptr::null_mut(); - - let result = unsafe { - cartesi_machine_sys::cm_log_uarch_step( - self.machine, - log_type.into(), - one_based, - &mut access_log, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; + // ------------------------------------ + // Reading and writing + // ------------------------------------ - Ok(log::AccessLog::new(access_log)) + /// Reads the value of a word in the machine state, by its physical address. + pub fn read_word(&mut self, address: u64) -> Result { + let mut value: u64 = 0; + let err_code = + unsafe { cartesi_machine_sys::cm_read_word(self.machine, address, &mut value) }; + check_err!(err_code)?; + + Ok(value) } - /// Checks the internal consistency of an access log produced by cm_log_uarch_step - pub fn verify_uarch_step_log( - &mut self, - log: &log::AccessLog, - one_based: bool, - ) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); - - let result = unsafe { - cartesi_machine_sys::cm_verify_uarch_step_log( - log.as_ptr(), - &self.runtime_config.values, - one_based, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; + /// Reads the value of a register. + pub fn read_reg(&mut self, reg: Register) -> Result { + let mut value: u64 = 0; + let err_code = unsafe { cartesi_machine_sys::cm_read_reg(self.machine, reg, &mut value) }; + check_err!(err_code)?; - Ok(()) + Ok(value) } - /// Checks the validity of a state transition - pub fn verify_uarch_step_state_transition( - &mut self, - root_hash_before: &hash::Hash, - log: &log::AccessLog, - root_hash_after: &hash::Hash, - one_based: bool, - ) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); - - let result = unsafe { - cartesi_machine_sys::cm_verify_uarch_step_state_transition( - root_hash_before.as_ptr(), - log.as_ptr(), - root_hash_after.as_ptr(), - &self.runtime_config.values, - one_based, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; + /// Writes the value of a register. + pub fn write_reg(&mut self, reg: Register, val: u64) -> Result<()> { + let err_code = unsafe { cartesi_machine_sys::cm_write_reg(self.machine, reg, val) }; + check_err!(err_code)?; Ok(()) } - /// Checks the validity of a state transition caused by a uarch state reset - pub fn verify_uarch_reset_state_transition( - &mut self, - root_hash_before: &hash::Hash, - log: &log::AccessLog, - root_hash_after: &hash::Hash, - one_based: bool, - ) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); - - let result = unsafe { - cartesi_machine_sys::cm_verify_uarch_reset_state_transition( - root_hash_before.as_ptr(), - log.as_ptr(), - root_hash_after.as_ptr(), - &self.runtime_config.values, - one_based, - error_collector.as_mut_ptr(), - ) + /// Reads a chunk of data from a machine memory range, by its physical address. + pub fn read_memory(&mut self, address: u64, size: u64) -> Result> { + let mut buffer = vec![0u8; size as usize]; + let err_code = unsafe { + cartesi_machine_sys::cm_read_memory(self.machine, address, buffer.as_mut_ptr(), size) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(()) + Ok(buffer) } - /// Checks the internal consistency of an access log produced by cm_log_uarch_reset - pub fn verify_uarch_reset_log( - &mut self, - log: &log::AccessLog, - one_based: bool, - ) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); - - let result = unsafe { - cartesi_machine_sys::cm_verify_uarch_reset_log( - log.as_ptr(), - &self.runtime_config.values, - one_based, - error_collector.as_mut_ptr(), + /// Writes a chunk of data to a machine memory range, by its physical address. + pub fn write_memory(&mut self, address: u64, data: &[u8]) -> Result<()> { + let err_code = unsafe { + cartesi_machine_sys::cm_write_memory( + self.machine, + address, + data.as_ptr(), + data.len() as u64, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; Ok(()) } - /// Obtains the proof for a node in the Merkle tree - pub fn get_proof( - &mut self, - address: u64, - log2_size: i32, - ) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut proof = std::ptr::null_mut(); - - let result = unsafe { - cartesi_machine_sys::cm_get_proof( + /// Reads a chunk of data from a machine memory range, by its virtual memory. + pub fn read_virtual_memory(&mut self, address: u64, size: u64) -> Result> { + let mut buffer = vec![0u8; size as usize]; + let err_code = unsafe { + cartesi_machine_sys::cm_read_virtual_memory( self.machine, address, - log2_size, - &mut proof, - error_collector.as_mut_ptr(), + buffer.as_mut_ptr(), + size, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(proof::MerkleTreeProof::new(proof)) + Ok(buffer) } - /// Obtains the root hash of the Merkle tree - pub fn get_root_hash(&mut self) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut hash = [0; 32]; - - let result = unsafe { - cartesi_machine_sys::cm_get_root_hash( + /// Writes a chunk of data to a machine memory range, by its virtual address. + pub fn write_virtual_memory(&mut self, address: u64, data: &[u8]) -> Result<()> { + let err_code = unsafe { + cartesi_machine_sys::cm_write_virtual_memory( self.machine, - &mut hash, - error_collector.as_mut_ptr(), + address, + data.as_ptr(), + data.len() as u64, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(hash::Hash::new(hash)) + Ok(()) } - /// Verifies integrity of Merkle tree. - pub fn verify_merkle_tree(&mut self) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut ret = false; - - let result = unsafe { - cartesi_machine_sys::cm_verify_merkle_tree( + /// Translates a virtual memory address to its corresponding physical memory address. + pub fn translate_virtual_address(&mut self, virtual_address: u64) -> Result { + let mut paddr: u64 = 0; + let err_code = unsafe { + cartesi_machine_sys::cm_translate_virtual_address( self.machine, - &mut ret, - error_collector.as_mut_ptr(), + virtual_address, + &mut paddr, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(ret) + Ok(paddr) } - /// Write the value of any CSR - pub fn write_csr(&mut self, csr: u32, value: u64) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + // ------------------------------------ + // Running + // ------------------------------------ - let result = unsafe { - cartesi_machine_sys::cm_write_csr( - self.machine, - csr as u32, - value, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; + /// Returns machine CM_REG_MCYCLE + pub fn mcycle(&mut self) -> Result { + self.read_reg(cartesi_machine_sys::CM_REG_MCYCLE) + } - Ok(()) + /// Returns machine CM_REG_IFLAGS_Y + pub fn iflags_y(&mut self) -> Result { + Ok(self.read_reg(cartesi_machine_sys::CM_REG_IFLAGS_Y)? != 0) } - /// Read the value of any CSR - pub fn read_csr(&mut self, csr: u32) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut value = 0; + /// Returns machine CM_REG_IFLAGS_H + pub fn iflags_h(&mut self) -> Result { + Ok(self.read_reg(cartesi_machine_sys::CM_REG_IFLAGS_H)? != 0) + } - let result = unsafe { - cartesi_machine_sys::cm_read_csr( - self.machine, - csr as u32, - &mut value, - error_collector.as_mut_ptr(), - ) + /// Returns machine CM_REG_UARCH_CYCLE + pub fn ucycle(&mut self) -> Result { + self.read_reg(cartesi_machine_sys::CM_REG_UARCH_CYCLE) + } + + /// Returns machine CM_REG_UARCH_HALT_FLAG + pub fn uarch_halt_flag(&mut self) -> Result { + Ok(self.read_reg(cartesi_machine_sys::CM_REG_UARCH_HALT_FLAG)? != 0) + } + + /// Runs the machine until CM_REG_MCYCLE reaches mcycle_end, machine yields, or halts. + pub fn run(&mut self, mcycle_end: u64) -> Result { + let mut break_reason = BreakReason::default(); + let cm_error = + unsafe { cartesi_machine_sys::cm_run(self.machine, mcycle_end, &mut break_reason) }; + check_err!(cm_error)?; + + Ok(break_reason) + } + + /// Runs the machine microarchitecture until CM_REG_UARCH_CYCLE reaches uarch_cycle_end or it halts. + pub fn run_uarch(&mut self, uarch_cycle_end: u64) -> Result { + let mut break_reason = UArchBreakReason::default(); + let err_code = unsafe { + cartesi_machine_sys::cm_run_uarch(self.machine, uarch_cycle_end, &mut break_reason) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(value) + Ok(break_reason) } - /// Gets the address of any CSR - pub fn get_csr_address(&mut self, csr: u32) -> u64 { - unsafe { cartesi_machine_sys::cm_get_csr_address(csr as u32) } + /// Resets the entire microarchitecture state to pristine values. + pub fn reset_uarch(&mut self) -> Result<()> { + let err_code = unsafe { cartesi_machine_sys::cm_reset_uarch(self.machine) }; + check_err!(err_code)?; + + Ok(()) } - /// Read the value of a word in the machine state. - pub fn read_word(&mut self, word_address: u64) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut word_value = 0; + /// Receives a cmio request. + pub fn receive_cmio_request(&mut self) -> Result { + let mut cmd: u8 = 0; + let mut reason: u16 = 0; + let mut length: u64 = 0; - let result = unsafe { - cartesi_machine_sys::cm_read_word( + // if data is NULL, length will still be set without reading any data. + let err_code = unsafe { + cartesi_machine_sys::cm_receive_cmio_request( self.machine, - word_address, - &mut word_value, - error_collector.as_mut_ptr(), + &mut cmd, + &mut reason, + ptr::null_mut(), + &mut length, ) }; - error_collector.collect(result)?; - - Ok(word_value) - } + check_err!(err_code)?; - /// Read a chunk of data from the machine memory. - pub fn read_memory(&mut self, address: u64, length: u64) -> Result, MachineError> { - let mut error_collector = ErrorCollector::new(); - let mut data = vec![0; length as usize]; + let mut buffer = vec![0u8; length as usize]; - let result = unsafe { - cartesi_machine_sys::cm_read_memory( + let err_code = unsafe { + cartesi_machine_sys::cm_receive_cmio_request( self.machine, - address, - data.as_mut_ptr(), - length, - error_collector.as_mut_ptr(), + &mut cmd, + &mut reason, + buffer.as_mut_ptr(), + &mut length, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(data) + Ok(CmioRequest::new(cmd, reason, buffer)) } - /// Write a chunk of data to the machine memory. - pub fn write_memory(&mut self, address: u64, data: &[u8]) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); - - let result = unsafe { - cartesi_machine_sys::cm_write_memory( + /// Sends a cmio response. + pub fn send_cmio_response(&mut self, reason: CmioResponseReason, data: &[u8]) -> Result<()> { + let err_code = unsafe { + cartesi_machine_sys::cm_send_cmio_response( self.machine, - address, + reason as u16, data.as_ptr(), - data.len(), - error_collector.as_mut_ptr(), + data.len() as u64, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; Ok(()) } - /// Reads a chunk of data from the machine virtual memory. - pub fn read_virtual_memory( - &mut self, - address: u64, - length: u64, - ) -> Result, MachineError> { - let mut error_collector = ErrorCollector::new(); - let mut data = vec![0; length as usize]; + // ------------------------------------ + // Logging + // ------------------------------------ - let result = unsafe { - cartesi_machine_sys::cm_read_virtual_memory( + /// Runs the machine for the given mcycle count and generates a log of accessed pages and proof data. + pub fn log_step(&mut self, mcycle_count: u64, log_filename: &Path) -> Result { + let mut break_reason = BreakReason::default(); + let log_filename_c = path_to_cstring(log_filename); + + let err_code = unsafe { + cartesi_machine_sys::cm_log_step( self.machine, - address, - data.as_mut_ptr(), - length, - error_collector.as_mut_ptr(), + mcycle_count, + log_filename_c.as_ptr(), + &mut break_reason, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(data) + Ok(break_reason) } - /// Writes a chunk of data to the machine virtual memory. - pub fn write_virtual_memory(&mut self, address: u64, data: &[u8]) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + /// Runs the machine in the microarchitecture for one micro cycle logging all accesses to the state. + pub fn log_step_uarch(&mut self, log_type: LogType) -> Result { + let mut log_ptr: *const c_char = ptr::null(); + let err_code = unsafe { + cartesi_machine_sys::cm_log_step_uarch(self.machine, log_type as i32, &mut log_ptr) + }; + check_err!(err_code)?; - let result = unsafe { - cartesi_machine_sys::cm_write_virtual_memory( + let access_log = parse_json_from_cstring!(log_ptr); + + Ok(access_log) + } + + /// Resets the entire microarchitecture state to pristine values logging all accesses to the state. + pub fn log_reset_uarch(&mut self, log_type: LogType) -> Result { + let mut log_ptr: *const c_char = ptr::null(); + let err_code = unsafe { + cartesi_machine_sys::cm_log_reset_uarch(self.machine, log_type as i32, &mut log_ptr) + }; + check_err!(err_code)?; + + let access_log = parse_json_from_cstring!(log_ptr); + + Ok(access_log) + } + + /// Sends a cmio response logging all accesses to the state. + pub fn log_send_cmio_response( + &mut self, + reason: CmioResponseReason, + data: &[u8], + log_type: LogType, + ) -> Result { + let mut log_ptr: *const c_char = ptr::null(); + let err_code = unsafe { + cartesi_machine_sys::cm_log_send_cmio_response( self.machine, - address, + reason as u16, data.as_ptr(), - data.len(), - error_collector.as_mut_ptr(), + data.len() as u64, + log_type as i32, + &mut log_ptr, + ) + }; + check_err!(err_code)?; + + let access_log = parse_json_from_cstring!(log_ptr); + + Ok(access_log) + } + + // ------------------------------------ + // Verifying + // ------------------------------------ + + /// Checks the validity of a step log file. + pub fn verify_step( + root_hash_before: &Hash, + log_filename: &Path, + mcycle_count: u64, + root_hash_after: &Hash, + ) -> Result { + let log_filename_c = path_to_cstring(log_filename); + + let mut break_reason = BreakReason::default(); + let err_code = unsafe { + cartesi_machine_sys::cm_verify_step( + ptr::null(), + root_hash_before, + log_filename_c.as_ptr(), + mcycle_count, + root_hash_after, + &mut break_reason, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(()) + Ok(break_reason) } - /// Reads the value of a general-purpose microarchitecture register. - pub fn read_x(&mut self, i: u32) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut value = 0; - - let result = unsafe { - cartesi_machine_sys::cm_read_x( - self.machine, - i as i32, - &mut value, - error_collector.as_mut_ptr(), + /// Checks the validity of a state transition produced by cm_log_step_uarch. + pub fn verify_step_uarch( + root_hash_before: &Hash, + log: &AccessLog, + root_hash_after: &Hash, + ) -> Result<()> { + let log_cstr = serialize_to_json!(&log); + + let err_code = unsafe { + cartesi_machine_sys::cm_verify_step_uarch( + ptr::null(), + root_hash_before, + log_cstr.as_ptr(), + root_hash_after, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; - Ok(value) + Ok(()) } - /// Writes the value of a general-purpose microarchitecture register. - pub fn write_x(&mut self, i: u32, value: u64) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + /// Checks the validity of a state transition produced by cm_log_verify_reset_uarch. + pub fn verify_reset_uarch( + root_hash_before: &Hash, + log: &AccessLog, + root_hash_after: &Hash, + ) -> Result<()> { + let log_cstr = serialize_to_json!(&log); + let err_code = unsafe { + cartesi_machine_sys::cm_verify_reset_uarch( + ptr::null(), + root_hash_before, + log_cstr.as_ptr(), + root_hash_after, + ) + }; + check_err!(err_code)?; - let result = unsafe { - cartesi_machine_sys::cm_write_x( - self.machine, - i as i32, - value, - error_collector.as_mut_ptr(), + Ok(()) + } + + /// Checks the validity of a state transition produced by cm_log_send_cmio_response. + pub fn verify_send_cmio_response( + reason: CmioResponseReason, + data: &[u8], + root_hash_before: &Hash, + log: &AccessLog, + root_hash_after: &Hash, + ) -> Result<()> { + let log_cstr = serialize_to_json!(&log); + + let err_code = unsafe { + cartesi_machine_sys::cm_verify_send_cmio_response( + ptr::null(), + reason as u16, + data.as_ptr(), + data.len() as u64, + root_hash_before, + log_cstr.as_ptr(), + root_hash_after, ) }; - error_collector.collect(result)?; + check_err!(err_code)?; Ok(()) } +} + +impl Machine { + fn last_error(code: i32) -> MachineError { + assert!(code != constants::error_code::OK); + + let msg_p = unsafe { cartesi_machine_sys::cm_get_last_error_message() }; + let cstr = unsafe { std::ffi::CStr::from_ptr(msg_p) }; + let message = String::from_utf8_lossy(cstr.to_bytes()).to_string(); - /// Gets the address of a general-purpose register. - pub fn get_x_address(&mut self, i: u32) -> u64 { - unsafe { cartesi_machine_sys::cm_get_x_address(i as i32) } + MachineError { code, message } } +} + +fn path_to_cstring(path: &Path) -> CString { + CString::new(path.to_string_lossy().as_bytes()).expect("CString::new failed") +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::{ + config::{ + machine::{MachineConfig, MemoryRangeConfig}, + runtime::RuntimeConfig, + }, + constants, + error::MachineResult as Result, + types::cmio::ManualReason, + }; - /// Gets the address of a general-purpose microarchitecture register. - pub fn get_uarch_x_address(&mut self, i: u32) -> u64 { - unsafe { cartesi_machine_sys::cm_get_uarch_x_address(i as i32) } + fn make_basic_machine_config() -> MachineConfig { + MachineConfig { + dtb: Some(crate::config::machine::DTBConfig { + entrypoint: Some("echo Hello from inside!".to_string()), + ..Default::default() + }), + flash_drive: Some(vec![MemoryRangeConfig { + image_filename: Some("../../../test/programs/rootfs.ext2".into()), + ..Default::default() + }]), + ram: crate::config::machine::RAMConfig { + length: 134217728, + image_filename: Some("../../../test/programs/linux.bin".into()), + }, + ..Default::default() + } } - /// Reads the value of a floating-point register. - pub fn read_f(&mut self, i: u32) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut value = 0; + fn make_cmio_machine_config() -> MachineConfig { + MachineConfig { + dtb: Some(crate::config::machine::DTBConfig { + entrypoint: Some( + "echo '{\"domain\":16,\"id\":\"'$(echo -n Hello from inside! | hex --encode)'\"}' \ + | rollup gio | grep -Eo '0x[0-9a-f]+' | tr -d '\\n' | hex --decode; echo" + .to_string(), + ), + ..Default::default() + }), + flash_drive: Some(vec![MemoryRangeConfig { + image_filename: Some("../../../test/programs/rootfs.ext2".into()), + ..Default::default() + }]), + ram: crate::config::machine::RAMConfig { + length: 134217728, + image_filename: Some("../../../test/programs/linux.bin".into()), + }, + ..Default::default() + } + } - let result = unsafe { - cartesi_machine_sys::cm_read_f( - self.machine, - i as i32, - &mut value, - error_collector.as_mut_ptr(), - ) + fn create_machine(config: &MachineConfig) -> Result { + let runtime_config = RuntimeConfig { + htif: Some(config::runtime::HTIFRuntimeConfig { + no_console_putchar: Some(true), + }), + ..Default::default() }; - error_collector.collect(result)?; + Machine::create(config, &runtime_config) + } - Ok(value) + #[test] + fn test_machine_run_halt_root_hash() -> Result<()> { + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; + + let break_reason = machine.run(u64::MAX)?; + assert_eq!(break_reason, constants::break_reason::HALTED); + + let mcycle_after_halt = machine.mcycle()?; + let root_hash_before = machine.root_hash()?; + + let break_reason = machine.run(u64::MAX)?; + assert_eq!(break_reason, constants::break_reason::HALTED); + + let root_hash_after = machine.root_hash()?; + assert_eq!(root_hash_before, root_hash_after,); + + let mcycle_after_second_run = machine.mcycle()?; + assert_eq!(mcycle_after_halt, mcycle_after_second_run,); + + Ok(()) } - /// Writes the value of a floating-point register. - pub fn write_f(&mut self, i: u32, value: u64) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + #[test] + fn test_machine_uarch_reset() -> Result<()> { + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; - let result = unsafe { - cartesi_machine_sys::cm_write_f( - self.machine, - i as i32, - value, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; + machine.run(1)?; + let reference_hash = machine.root_hash()?; + let initial_config = machine.initial_config()?; + drop(machine); + + let mut machine = create_machine(&initial_config)?; + + let uarch_break_reason = machine.run_uarch(u64::MAX)?; + assert_eq!( + uarch_break_reason, + constants::uarch_break_reason::UARCH_HALTED + ); + + machine.reset_uarch()?; + + let final_hash = machine.root_hash()?; + assert_eq!(reference_hash, final_hash,); + + let ucycle = machine.ucycle()?; + assert_eq!(ucycle, 0); + + Ok(()) + } + + #[test] + fn test_runtime_config_round_trip() -> Result<()> { + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; + + let original_config = machine.runtime_config()?; + machine.set_runtime_config(&original_config)?; Ok(()) } - /// Gets the address of a floating-point register. - pub fn get_f_address(&mut self, i: u32) -> u64 { - unsafe { cartesi_machine_sys::cm_get_f_address(i as i32) } + #[test] + fn test_log_step() -> Result<()> { + let tmp_dir = tempfile::tempdir().expect("failed creating a temp dir"); + let log_path = tmp_dir.path().join("machine_step.log"); + + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; + + let root_hash_before = machine.root_hash()?; + + machine.log_step(50, &log_path)?; + let root_hash_after = machine.root_hash()?; + + let verified_break_reason = + Machine::verify_step(&root_hash_before, &log_path, 50, &root_hash_after)?; + assert_ne!(verified_break_reason, constants::break_reason::FAILED); + + Ok(()) } - /// Returns copy of initialization config. - pub fn initial_config(&self) -> Result { - MachineConfigRef::try_new(self) + #[test] + fn test_log_step_uarch() -> Result<()> { + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; + + let root_hash_before = machine.root_hash()?; + let access_log: AccessLog = machine.log_step_uarch(LogType::LargeData)?; + let root_hash_after = machine.root_hash()?; + + Machine::verify_step_uarch(&root_hash_before, &access_log, &root_hash_after)?; + + Ok(()) } - /// Returns copy of default system config. - pub fn default_config() -> MachineConfigRef { - MachineConfigRef::default() + #[test] + fn test_log_reset_uarch() -> Result<()> { + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; + + let root_hash_before = machine.root_hash()?; + let reset_log = machine.log_reset_uarch(LogType::Annotations)?; + let root_hash_after = machine.root_hash()?; + + Machine::verify_reset_uarch(&root_hash_before, &reset_log, &root_hash_after)?; + + Ok(()) } - /// Replaces a memory range - pub fn replace_memory_range( - &mut self, - new_range: &MemoryRangeConfig, - ) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + #[test] + fn test_log_send_cmio_response() -> Result<()> { + let config = make_cmio_machine_config(); + let mut machine = create_machine(&config)?; - let result = unsafe { - cartesi_machine_sys::cm_replace_memory_range( - self.machine, - new_range, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; + let break_reason = machine.run(u64::MAX)?; + assert_eq!(break_reason, constants::break_reason::YIELDED_MANUALLY); + + let root_hash_before = machine.root_hash()?; + + let request = machine.receive_cmio_request()?; + assert!(matches!( + request, + CmioRequest::Manual(ManualReason::GIO { domain: 16, ref data }) + if data == b"Hello from inside!" + )); + let response_data = b"Hello from outside!"; + let access_log: AccessLog = machine.log_send_cmio_response( + CmioResponseReason::Advance, + response_data, + LogType::LargeData, + )?; + + let root_hash_after = machine.root_hash()?; + + Machine::verify_send_cmio_response( + CmioResponseReason::Advance, + response_data, + &root_hash_before, + &access_log, + &root_hash_after, + )?; Ok(()) } - /// Verify if dirty page maps are consistent. - pub fn verify_dirty_page_maps(&mut self) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut ret = false; + #[test] + fn test_machine_cmio() -> Result<()> { + let cmio_config = make_cmio_machine_config(); + let mut machine = create_machine(&cmio_config)?; - let result = unsafe { - cartesi_machine_sys::cm_verify_dirty_page_maps( - self.machine, - &mut ret, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; + let break_reason = machine.run(u64::MAX)?; + assert_eq!(break_reason, constants::break_reason::YIELDED_MANUALLY); - Ok(ret) + let request = machine.receive_cmio_request()?; + assert!(matches!( + request, + CmioRequest::Manual(ManualReason::GIO { domain: 16, ref data }) + if data == b"Hello from inside!" + )); + + let response = b"Hello from outside!"; + machine.send_cmio_response(CmioResponseReason::Advance, response)?; + + let break_reason = machine.run(u64::MAX)?; + assert_eq!(break_reason, constants::break_reason::HALTED); + + Ok(()) } - /// Resets the value of the microarchitecture halt flag. - pub fn log_uarch_reset( - &mut self, - log_type: log::AccessLogType, - one_based: bool, - ) -> Result { - let mut error_collector = ErrorCollector::new(); - let mut access_log = std::ptr::null_mut(); - - let result = unsafe { - cartesi_machine_sys::cm_log_uarch_reset( - self.machine, - log_type.into(), - one_based, - &mut access_log, - error_collector.as_mut_ptr(), - ) - }; - error_collector.collect(result)?; + #[test] + fn test_store_and_load_machine() -> Result<()> { + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; + + let break_reason = machine.run(1000)?; + assert_eq!(break_reason, constants::break_reason::REACHED_TARGET_MCYCLE); + let root_hash_before_store = machine.root_hash()?; + + let tmp_dir = tempfile::tempdir().expect("failed creating a temp dir"); + let store_path = tmp_dir.path().join("image"); + machine.store(&store_path)?; + + let runtime_config = RuntimeConfig::default(); + let mut machine = Machine::load(&store_path, &runtime_config)?; + + let root_hash_after_load = machine.root_hash()?; + assert_eq!(root_hash_before_store, root_hash_after_load,); - Ok(log::AccessLog::new(access_log)) + Ok(()) } -} -macro_rules! read_csr { - ($typ: ty, $name: ident, $flag: ident) => { - pub fn $name(&self) -> Result<$typ, MachineError> { - let mut error_collector = ErrorCollector::new(); - let mut value: $typ = Default::default(); + #[test] + fn test_memory_range() -> Result<()> { + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; - let result = unsafe { - cartesi_machine_sys::$flag(self.machine, &mut value, error_collector.as_mut_ptr()) - }; - error_collector.collect(result)?; + let ranges_before = machine.memory_ranges()?; + assert!(!ranges_before.is_empty()); - Ok(value) - } - }; -} + let range = ranges_before.last().unwrap(); -macro_rules! write_csr { - ($typ: ty, $name: ident, $flag: ident) => { - pub fn $name(&mut self, value: $typ) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + let mem = machine.read_memory(range.start, range.length)?; + assert!(mem.iter().any(|x| *x != 0)); - let result = unsafe { - cartesi_machine_sys::$flag(self.machine, value, error_collector.as_mut_ptr()) - }; - error_collector.collect(result)?; + // writes zeroes in range + machine.replace_memory_range(range.start, range.length, false, None)?; + let mem = machine.read_memory(range.start, range.length)?; + assert!(!mem.iter().any(|x| *x != 0)); - Ok(()) - } - }; -} + // write ones in range + machine.write_memory(range.start, &vec![1; range.length as usize])?; + let mem = machine.read_memory(range.start, range.length)?; + assert!(mem.iter().all(|x| *x == 1)); -macro_rules! iflags { - ($name: ident, $flag: ident) => { - pub fn $name(&mut self) -> Result<(), MachineError> { - let mut error_collector = ErrorCollector::new(); + let log2_size = u64::BITS - range.length.leading_zeros(); + let proof: Proof = machine.proof(range.start, u64::BITS - range.length.leading_zeros())?; + assert_eq!(proof.target_address, range.start); + assert_eq!(proof.log2_target_size, log2_size as u64); - let result = - unsafe { cartesi_machine_sys::$flag(self.machine, error_collector.as_mut_ptr()) }; - error_collector.collect(result)?; + Ok(()) + } - Ok(()) - } - }; -} + #[test] + fn test_memory_ops() -> Result<()> { + let config = make_basic_machine_config(); + let mut machine = create_machine(&config)?; -impl Machine { - iflags!(set_iflags_x, cm_set_iflags_X); - iflags!(reset_iflags_x, cm_reset_iflags_X); - iflags!(set_iflags_y, cm_set_iflags_Y); - iflags!(reset_iflags_y, cm_reset_iflags_Y); - iflags!(set_iflags_h, cm_set_iflags_H); - iflags!(set_uarch_halt_flag, cm_set_uarch_halt_flag); - iflags!(reset_uarch, cm_reset_uarch); - - read_csr!(u64, read_pc, cm_read_pc); - read_csr!(u64, read_fcsr, cm_read_fcsr); - read_csr!(u64, read_mvendorid, cm_read_mvendorid); - read_csr!(u64, read_marchid, cm_read_marchid); - read_csr!(u64, read_mimpid, cm_read_mimpid); - read_csr!(u64, read_mcycle, cm_read_mcycle); - read_csr!(u64, read_icycleinstret, cm_read_icycleinstret); - read_csr!(u64, read_mstatus, cm_read_mstatus); - read_csr!(u64, read_menvcfg, cm_read_menvcfg); - read_csr!(u64, read_mtvec, cm_read_mtvec); - read_csr!(u64, read_mscratch, cm_read_mscratch); - read_csr!(u64, read_mepc, cm_read_mepc); - read_csr!(u64, read_mcause, cm_read_mcause); - read_csr!(u64, read_mtval, cm_read_mtval); - read_csr!(u64, read_misa, cm_read_misa); - read_csr!(u64, read_mie, cm_read_mie); - read_csr!(u64, read_mip, cm_read_mip); - read_csr!(u64, read_medeleg, cm_read_medeleg); - read_csr!(u64, read_mideleg, cm_read_mideleg); - read_csr!(u64, read_mcounteren, cm_read_mcounteren); - read_csr!(u64, read_stvec, cm_read_stvec); - read_csr!(u64, read_sscratch, cm_read_sscratch); - read_csr!(u64, read_sepc, cm_read_sepc); - read_csr!(u64, read_scause, cm_read_scause); - read_csr!(u64, read_stval, cm_read_stval); - read_csr!(u64, read_satp, cm_read_satp); - read_csr!(u64, read_scounteren, cm_read_scounteren); - read_csr!(u64, read_senvcfg, cm_read_senvcfg); - read_csr!(u64, read_ilrsc, cm_read_ilrsc); - read_csr!(u64, read_iflags, cm_read_iflags); - read_csr!(u64, read_htif_tohost, cm_read_htif_tohost); - read_csr!(u64, read_htif_tohost_dev, cm_read_htif_tohost_dev); - read_csr!(u64, read_htif_tohost_cmd, cm_read_htif_tohost_cmd); - read_csr!(u64, read_htif_tohost_data, cm_read_htif_tohost_data); - read_csr!(u64, read_htif_fromhost, cm_read_htif_fromhost); - read_csr!(u64, read_htif_ihalt, cm_read_htif_ihalt); - read_csr!(u64, read_htif_iconsole, cm_read_htif_iconsole); - read_csr!(u64, read_htif_iyield, cm_read_htif_iyield); - read_csr!(u64, read_clint_mtimecmp, cm_read_clint_mtimecmp); - read_csr!(bool, read_iflags_x, cm_read_iflags_X); - read_csr!(bool, read_iflags_y, cm_read_iflags_Y); - read_csr!(bool, read_iflags_h, cm_read_iflags_H); - read_csr!(u64, read_uarch_pc, cm_read_uarch_pc); - read_csr!(u64, read_uarch_cycle, cm_read_uarch_cycle); - read_csr!(bool, read_uarch_halt_flag, cm_read_uarch_halt_flag); - - write_csr!(u64, write_pc, cm_write_pc); - write_csr!(u64, write_fcsr, cm_write_fcsr); - write_csr!(u64, write_mcycle, cm_write_mcycle); - write_csr!(u64, write_icycleinstret, cm_write_icycleinstret); - write_csr!(u64, write_mstatus, cm_write_mstatus); - write_csr!(u64, write_menvcfg, cm_write_menvcfg); - write_csr!(u64, write_mtvec, cm_write_mtvec); - write_csr!(u64, write_mscratch, cm_write_mscratch); - write_csr!(u64, write_mepc, cm_write_mepc); - write_csr!(u64, write_mcause, cm_write_mcause); - write_csr!(u64, write_mtval, cm_write_mtval); - write_csr!(u64, write_misa, cm_write_misa); - write_csr!(u64, write_mie, cm_write_mie); - write_csr!(u64, write_mip, cm_write_mip); - write_csr!(u64, write_medeleg, cm_write_medeleg); - write_csr!(u64, write_mideleg, cm_write_mideleg); - write_csr!(u64, write_mcounteren, cm_write_mcounteren); - write_csr!(u64, write_stvec, cm_write_stvec); - write_csr!(u64, write_sscratch, cm_write_sscratch); - write_csr!(u64, write_sepc, cm_write_sepc); - write_csr!(u64, write_scause, cm_write_scause); - write_csr!(u64, write_stval, cm_write_stval); - write_csr!(u64, write_satp, cm_write_satp); - write_csr!(u64, write_scounteren, cm_write_scounteren); - write_csr!(u64, write_senvcfg, cm_write_senvcfg); - write_csr!(u64, write_ilrsc, cm_write_ilrsc); - write_csr!(u64, write_iflags, cm_write_iflags); - write_csr!(u64, write_htif_tohost, cm_write_htif_tohost); - write_csr!(u64, write_htif_fromhost, cm_write_htif_fromhost); - write_csr!(u64, write_htif_ihalt, cm_write_htif_ihalt); - write_csr!(u64, write_htif_iconsole, cm_write_htif_iconsole); - write_csr!(u64, write_htif_iyield, cm_write_htif_iyield); - write_csr!(u64, write_clint_mtimecmp, cm_write_clint_mtimecmp); - write_csr!(u64, write_uarch_pc, cm_write_uarch_pc); - write_csr!(u64, write_uarch_cycle, cm_write_uarch_cycle); -} + let reg = cartesi_machine_sys::CM_REG_X1; + let reg_phys_addr = Machine::reg_address(reg)?; + + let val_via_read_word = machine.read_word(reg_phys_addr)?; + let val_via_read_reg = machine.read_reg(reg)?; + assert_eq!(val_via_read_word, val_via_read_reg); + + let new_reg_value = 0x1234_5678_9ABC_DEF0; + machine.write_reg(reg, new_reg_value)?; + let val_via_read_word2 = machine.read_word(reg_phys_addr)?; + assert_eq!(val_via_read_word2, new_reg_value); + + let val_via_read_reg2 = machine.read_reg(reg)?; + assert_eq!(val_via_read_reg2, new_reg_value); -/// Returns packed iflags from its component fields. -pub fn packed_iflags(prv: i32, x: i32, y: i32, h: i32) -> u64 { - unsafe { cartesi_machine_sys::cm_packed_iflags(prv, x, y, h) } + // let another_value: u64 = 0xDEAD_BEEF_0000_0001; + // let data_bytes = another_value.to_le_bytes(); + // machine.write_memory(reg_phys_addr, &data_bytes)?; + + Ok(()) + } } diff --git a/machine/rust-bindings/cartesi-machine/src/proof.rs b/machine/rust-bindings/cartesi-machine/src/proof.rs deleted file mode 100644 index 38e93254..00000000 --- a/machine/rust-bindings/cartesi-machine/src/proof.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! Structures for merkle proofs - -use crate::hash::Hash; - -/// Merkle tree proof structure -pub struct MerkleTreeProof(*mut cartesi_machine_sys::cm_merkle_tree_proof); - -impl Drop for MerkleTreeProof { - fn drop(&mut self) { - unsafe { cartesi_machine_sys::cm_delete_merkle_tree_proof(self.0) }; - } -} - -impl MerkleTreeProof { - pub(crate) fn new(ptr: *mut cartesi_machine_sys::cm_merkle_tree_proof) -> Self { - Self(ptr) - } - - /// Address of the target node - pub fn target_address(&self) -> u64 { - unsafe { (*self.0).target_address } - } - - /// Log2 of size of target node - pub fn log2_target_size(&self) -> usize { - unsafe { (*self.0).log2_target_size } - } - - /// Hash of target node - pub fn target_hash(&self) -> Hash { - Hash::new(unsafe { (*self.0).target_hash }) - } - - /// Log2 of size of root node - pub fn log2_root_size(&self) -> usize { - unsafe { (*self.0).log2_root_size } - } - - /// Hash of root node - pub fn root_hash(&self) -> Hash { - Hash::new(unsafe { (*self.0).root_hash }) - } - - /// Sibling hashes towards root - pub fn sibling_hashes(&self) -> Vec { - let sibling_hashes = unsafe { (*self.0).sibling_hashes }; - let sibling_hashes = - unsafe { std::slice::from_raw_parts(sibling_hashes.entry, sibling_hashes.count) }; - - sibling_hashes.iter().map(|hash| Hash::new(*hash)).collect() - } -} diff --git a/machine/rust-bindings/cartesi-machine/src/types/access_proof.rs b/machine/rust-bindings/cartesi-machine/src/types/access_proof.rs new file mode 100644 index 00000000..6a4c5f3c --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/types/access_proof.rs @@ -0,0 +1,91 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use crate::types::{base64_decode::*, Hash}; +use serde::{Deserialize, Serialize}; + +pub type NoteArray = Vec; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum BracketType { + Begin, + End, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum AccessType { + Read, + Write, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Bracket { + pub r#type: BracketType, + pub r#where: u64, + pub text: String, +} + +pub type BracketArray = Vec; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Access { + pub r#type: AccessType, + pub address: u64, + pub log2_size: u64, + + #[serde( + deserialize_with = "deserialize_base64_32", + serialize_with = "serialize_base64_32" + )] + pub read_hash: Hash, + + #[serde( + deserialize_with = "deserialize_base64_vec_opt", + serialize_with = "serialize_base64_vec_opt", + default, + skip_serializing_if = "Option::is_none" + )] + pub read: Option>, + + #[serde( + deserialize_with = "deserialize_base64_32_opt", + serialize_with = "serialize_base64_32_opt", + default, + skip_serializing_if = "Option::is_none" + )] + pub written_hash: Option, + + #[serde( + deserialize_with = "deserialize_base64_vec_opt", + serialize_with = "serialize_base64_vec_opt", + default, + skip_serializing_if = "Option::is_none" + )] + pub written: Option>, + + #[serde( + deserialize_with = "deserialize_base64_32_array_opt", + serialize_with = "serialize_base64_32_array_opt", + default, + skip_serializing_if = "Option::is_none" + )] + pub sibling_hashes: Option>, +} + +pub type AccessArray = Vec; + +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +pub struct AccessLogType { + pub has_annotations: bool, + pub has_large_data: bool, +} + +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +pub struct AccessLog { + pub log_type: AccessLogType, + pub accesses: AccessArray, + pub notes: Option, + pub brackets: Option, +} diff --git a/machine/rust-bindings/cartesi-machine/src/types/base64_decode.rs b/machine/rust-bindings/cartesi-machine/src/types/base64_decode.rs new file mode 100644 index 00000000..ee9a874e --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/types/base64_decode.rs @@ -0,0 +1,299 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use crate::types::Hash; +use base64::{prelude::BASE64_STANDARD, Engine}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +macro_rules! decode_base64_str { + ($base64_string:expr) => { + BASE64_STANDARD + .decode($base64_string) + .map_err(|err| serde::de::Error::custom(format!("base64 decode error: {err}"))) + }; +} + +macro_rules! encode_to_base64_str { + ($bytes:expr) => { + BASE64_STANDARD.encode($bytes) + }; +} + +macro_rules! unwrap_ref { + ($val:expr) => { + $val.as_ref().expect("serde should skip when None") + }; +} + +macro_rules! decode_base64_hash { + ($base64_string:expr) => {{ + let bytes = decode_base64_str!($base64_string)?; + if bytes.len() != 32 { + Err(serde::de::Error::invalid_length(bytes.len(), &"32")) + } else { + let mut hash = Hash::default(); + hash.copy_from_slice(&bytes); + Ok(hash) + } + }}; +} + +#[allow(dead_code)] +pub fn deserialize_base64_vec<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let base64_string = String::deserialize(deserializer)?; + decode_base64_str!(&base64_string) +} + +#[allow(dead_code)] +pub fn serialize_base64_vec(val: &Vec, serializer: S) -> Result +where + S: Serializer, +{ + let encoded = encode_to_base64_str!(&val); + serializer.serialize_str(&encoded) +} + +pub fn deserialize_base64_vec_opt<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let opt_str = Option::::deserialize(deserializer)?; + + match opt_str { + None => Ok(None), + Some(base64_string) => Ok(Some(decode_base64_str!(&base64_string)?)), + } +} + +pub fn serialize_base64_vec_opt(val: &Option>, serializer: S) -> Result +where + S: Serializer, +{ + let encoded = encode_to_base64_str!(unwrap_ref!(&val)); + serializer.serialize_str(&encoded) +} + +pub fn deserialize_base64_32<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let base64_string = String::deserialize(deserializer)?; + decode_base64_hash!(&base64_string) +} + +pub fn serialize_base64_32(val: &Hash, serializer: S) -> Result +where + S: Serializer, +{ + let encoded = encode_to_base64_str!(&val); + serializer.serialize_str(&encoded) +} + +pub fn deserialize_base64_32_opt<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let opt_str = Option::::deserialize(deserializer)?; + match opt_str { + None => Ok(None), + Some(base64_string) => Ok(Some(decode_base64_hash!(&base64_string)?)), + } +} + +pub fn serialize_base64_32_opt(val: &Option, serializer: S) -> Result +where + S: Serializer, +{ + let encoded = encode_to_base64_str!(unwrap_ref!(&val)); + serializer.serialize_str(&encoded) +} + +pub fn deserialize_base64_32_array<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let strings = Vec::::deserialize(deserializer)?; + let mut out = Vec::with_capacity(strings.len()); + + for base64_string in strings { + out.push(decode_base64_hash!(&base64_string)?); + } + + Ok(out) +} + +pub fn serialize_base64_32_array(val: &[Hash], serializer: S) -> Result +where + S: Serializer, +{ + let encoded: Vec = val.iter().map(|arr| encode_to_base64_str!(&arr)).collect(); + + encoded.serialize(serializer) +} + +pub fn deserialize_base64_32_array_opt<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let opt_strings = Option::>::deserialize(deserializer)?; + + match opt_strings { + None => Ok(None), + Some(strings) => { + let mut out = Vec::with_capacity(strings.len()); + for base64_string in strings { + out.push(decode_base64_hash!(&base64_string)?); + } + Ok(Some(out)) + } + } +} + +pub fn serialize_base64_32_array_opt( + val: &Option>, + serializer: S, +) -> Result +where + S: Serializer, +{ + let hashes = unwrap_ref!(&val); + + // Map each Hash to a base64 string + let encoded: Vec = hashes + .iter() + .map(|arr| encode_to_base64_str!(&arr)) + .collect(); + + encoded.serialize(serializer) +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::from_str; + + use serde::Deserialize; + + #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] + pub struct Foo { + #[serde( + deserialize_with = "deserialize_base64_vec", + serialize_with = "serialize_base64_vec" + )] + pub bytes: Vec, + + #[serde( + deserialize_with = "deserialize_base64_vec_opt", + serialize_with = "serialize_base64_vec_opt", + default, + skip_serializing_if = "Option::is_none" + )] + pub bytes_opt: Option>, + + #[serde( + deserialize_with = "deserialize_base64_32", + serialize_with = "serialize_base64_32" + )] + pub hash: Hash, + + #[serde( + deserialize_with = "deserialize_base64_32_opt", + serialize_with = "serialize_base64_32_opt", + default, + skip_serializing_if = "Option::is_none" + )] + pub hash_opt: Option, + + #[serde( + deserialize_with = "deserialize_base64_32_array", + serialize_with = "serialize_base64_32_array" + )] + pub hashes: Vec, + + #[serde( + deserialize_with = "deserialize_base64_32_array_opt", + serialize_with = "serialize_base64_32_array_opt", + default, + skip_serializing_if = "Option::is_none" + )] + pub hashes_opt: Option>, + } + + #[test] + fn test_deserialize_base64() { + let json_data = r#" + { + "bytes": "SGVsbG8gV29ybGQh", + "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "hashes": [ + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE=" + ] + } + "#; + + let proof: Foo = from_str(json_data).expect("should deserialize fine"); + + // bytes -> "Hello World!" + assert_eq!(proof.bytes, b"Hello World!"); + + // hash -> 32 bytes of zeros + assert_eq!(proof.hash, [0u8; 32]); + + // hashes -> first is 32 zeros, second is 32 ones + assert_eq!(proof.hashes.len(), 2); + assert_eq!(proof.hashes[0], [0u8; 32]); + assert_eq!(proof.hashes[1], [1u8; 32]); + + assert!(proof.bytes_opt.is_none()); + assert!(proof.hash_opt.is_none()); + assert!(proof.hashes_opt.is_none()); + + assert_eq!( + proof, + from_str(&serde_json::to_string(&proof).unwrap()).unwrap() + ); + } + + #[test] + fn test_deserialize_proof_with_all_fields() { + let json_data = r#" + { + "bytes_opt": "SGVsbG8gV29ybGQh", + "bytes": "SGVsbG8gV29ybGQh", + + "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "hash_opt": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + + "hashes": [ + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE=" + ], + "hashes_opt": [ + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE=" + ] + } + "#; + + let proof: Foo = from_str(json_data).expect("should deserialize fine"); + assert_eq!(proof.bytes, b"Hello World!".to_vec()); + assert_eq!(proof.bytes_opt, Some(b"Hello World!".to_vec())); + assert_eq!(proof.hash, [0u8; 32]); + assert_eq!(proof.hash_opt, Some([0u8; 32])); + assert_eq!(proof.hashes.len(), 2); + assert_eq!(proof.hashes[1], [1u8; 32]); + assert_eq!(proof.hashes_opt.as_ref().unwrap().len(), 2); + assert_eq!(proof.hashes_opt.as_ref().unwrap()[1], [1u8; 32]); + + assert_eq!( + proof, + from_str(&serde_json::to_string(&proof).unwrap()).unwrap() + ); + } +} diff --git a/machine/rust-bindings/cartesi-machine/src/types/cmio.rs b/machine/rust-bindings/cartesi-machine/src/types/cmio.rs new file mode 100644 index 00000000..141356ab --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/types/cmio.rs @@ -0,0 +1,155 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use crate::{constants, types::Hash}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum CmioRequest { + Automatic(AutomaticReason), + Manual(ManualReason), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum AutomaticReason { + Progress { mille_progress: u32 }, + TxOutput { data: Vec }, + TxReport { data: Vec }, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum ManualReason { + RxAccepted { output_hashes_root_hash: Hash }, + RxRejected, + TxException { message: String }, + GIO { domain: u16, data: Vec }, +} + +impl CmioRequest { + pub fn new(cmd: u8, reason: u16, data: Vec) -> Self { + use constants::cmio::{commands, tohost::automatic, tohost::manual}; + match cmd { + commands::YIELD_AUTOMATIC => Self::Automatic(match reason { + automatic::PROGRESS => AutomaticReason::Progress { + mille_progress: u32::from_le_bytes( + data.try_into().expect("malformed progress integer"), + ), + }, + automatic::TX_OUTPUT => AutomaticReason::TxOutput { data }, + automatic::TX_REPORT => AutomaticReason::TxReport { data }, + _ => panic!("Unknown automatic yield reason {}", reason), + }), + + commands::YIELD_MANUAL => Self::Manual(match reason { + manual::RX_ACCEPTED => ManualReason::RxAccepted { + output_hashes_root_hash: data + .try_into() + .expect("malformed `output_hashes_root_hash`"), + }, + manual::RX_REJECTED => ManualReason::RxRejected, + manual::TX_EXCEPTION => ManualReason::TxException { + message: String::from_utf8_lossy(&data).into_owned(), + }, + domain => ManualReason::GIO { domain, data }, + }), + _ => panic!("Unknown cmio command {}", cmd), + } + } + + pub fn cmd_and_reason(&self) -> (u8, u16) { + use constants::cmio::{commands, tohost::automatic, tohost::manual}; + match self { + CmioRequest::Automatic(automatic_reason) => ( + commands::YIELD_AUTOMATIC, + match automatic_reason { + AutomaticReason::Progress { .. } => automatic::PROGRESS, + AutomaticReason::TxOutput { .. } => automatic::TX_OUTPUT, + AutomaticReason::TxReport { .. } => automatic::TX_REPORT, + }, + ), + CmioRequest::Manual(manual_reason) => ( + commands::YIELD_MANUAL, + match manual_reason { + ManualReason::RxAccepted { .. } => manual::RX_ACCEPTED, + ManualReason::RxRejected => manual::RX_REJECTED, + ManualReason::TxException { .. } => manual::TX_EXCEPTION, + ManualReason::GIO { domain, .. } => *domain, + }, + ), + } + } + + pub fn cmd(&self) -> u8 { + self.cmd_and_reason().0 + } + + pub fn reason(&self) -> u16 { + self.cmd_and_reason().1 + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum CmioResponseReason { + Advance = cartesi_machine_sys::CM_CMIO_YIELD_REASON_ADVANCE_STATE as isize, + Inspect = cartesi_machine_sys::CM_CMIO_YIELD_REASON_INSPECT_STATE as isize, +} + +#[cfg(test)] +mod tests { + use super::*; + use constants::cmio; + + macro_rules! test_req { + ($cmd:expr, $reason:expr, $data:expr, $expected:expr) => {{ + let r = CmioRequest::new($cmd, $reason, $data); + assert_eq!(r, $expected); + assert_eq!(r.cmd_and_reason(), ($cmd, $reason)); + assert_eq!(r.cmd(), $cmd); + assert_eq!(r.reason(), $reason); + }}; + } + + #[test] + fn test_cmio_contructor() { + test_req!( + cmio::commands::YIELD_AUTOMATIC, + cmio::tohost::automatic::TX_REPORT, + vec![], + CmioRequest::Automatic(AutomaticReason::TxReport { data: vec![] }) + ); + test_req!( + cmio::commands::YIELD_AUTOMATIC, + cmio::tohost::automatic::TX_OUTPUT, + vec![], + CmioRequest::Automatic(AutomaticReason::TxOutput { data: vec![] }) + ); + test_req!( + cmio::commands::YIELD_AUTOMATIC, + cmio::tohost::automatic::PROGRESS, + 42u32.to_ne_bytes().to_vec(), + CmioRequest::Automatic(AutomaticReason::Progress { mille_progress: 42 }) + ); + + test_req!( + cmio::commands::YIELD_MANUAL, + cmio::tohost::manual::RX_ACCEPTED, + vec![0; 32], + CmioRequest::Manual(ManualReason::RxAccepted { + output_hashes_root_hash: Hash::default() + }) + ); + test_req!( + cmio::commands::YIELD_MANUAL, + cmio::tohost::manual::RX_REJECTED, + vec![], + CmioRequest::Manual(ManualReason::RxRejected) + ); + test_req!( + cmio::commands::YIELD_MANUAL, + cmio::tohost::manual::TX_EXCEPTION, + vec![], + CmioRequest::Manual(ManualReason::TxException { + message: "".to_owned() + }) + ); + } +} diff --git a/machine/rust-bindings/cartesi-machine/src/types/memory_proof.rs b/machine/rust-bindings/cartesi-machine/src/types/memory_proof.rs new file mode 100644 index 00000000..8b0986f3 --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/types/memory_proof.rs @@ -0,0 +1,31 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use crate::types::{base64_decode::*, Hash}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Proof { + pub target_address: u64, + pub log2_target_size: u64, + + #[serde( + deserialize_with = "deserialize_base64_32", + serialize_with = "serialize_base64_32" + )] + pub target_hash: Hash, + + pub log2_root_size: u64, + + #[serde( + deserialize_with = "deserialize_base64_32", + serialize_with = "serialize_base64_32" + )] + pub root_hash: Hash, + + #[serde( + deserialize_with = "deserialize_base64_32_array", + serialize_with = "serialize_base64_32_array" + )] + pub sibling_hashes: Vec, +} diff --git a/machine/rust-bindings/cartesi-machine/src/types/memory_range.rs b/machine/rust-bindings/cartesi-machine/src/types/memory_range.rs new file mode 100644 index 00000000..630c9944 --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/types/memory_range.rs @@ -0,0 +1,13 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use serde::Deserialize; + +#[derive(Clone, Debug, Default, Deserialize)] +pub struct MemoryRangeDescription { + pub start: u64, + pub length: u64, + pub description: Option, +} + +pub type MemoryRangeDescriptions = Vec; diff --git a/machine/rust-bindings/cartesi-machine/src/types/mod.rs b/machine/rust-bindings/cartesi-machine/src/types/mod.rs new file mode 100644 index 00000000..bf8b712d --- /dev/null +++ b/machine/rust-bindings/cartesi-machine/src/types/mod.rs @@ -0,0 +1,20 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +pub mod access_proof; +pub mod cmio; +pub mod memory_proof; +pub mod memory_range; + +pub type Hash = cartesi_machine_sys::cm_hash; +pub type Register = cartesi_machine_sys::cm_reg; +pub type BreakReason = cartesi_machine_sys::cm_break_reason; +pub type UArchBreakReason = cartesi_machine_sys::cm_uarch_break_reason; + +#[derive(Clone, Debug)] +pub enum LogType { + Annotations = crate::constants::access_log_type::ANNOTATIONS as isize, + LargeData = crate::constants::access_log_type::LARGE_DATA as isize, +} + +mod base64_decode; diff --git a/machine/rust-bindings/cartesi-machine/src/utils.rs b/machine/rust-bindings/cartesi-machine/src/utils.rs deleted file mode 100644 index bf1e546e..00000000 --- a/machine/rust-bindings/cartesi-machine/src/utils.rs +++ /dev/null @@ -1,14 +0,0 @@ -// (c) Cartesi and individual authors (see AUTHORS) -// SPDX-License-Identifier: Apache-2.0 (see LICENSE) - -//! This module contains functions for converting between Rust and C strings. - -use std::ffi::{c_char, CStr}; - -pub(crate) fn from_cstr(cstr: *const c_char) -> Option { - if cstr.is_null() { - None - } else { - unsafe { Some(CStr::from_ptr(cstr).to_string_lossy().into_owned()) } - } -} diff --git a/prt/client-rs/core/src/machine/instance.rs b/prt/client-rs/core/src/machine/instance.rs index e341463b..9c945c7f 100644 --- a/prt/client-rs/core/src/machine/instance.rs +++ b/prt/client-rs/core/src/machine/instance.rs @@ -2,11 +2,10 @@ use crate::db::compute_state_access::{ComputeStateAccess, Input}; use crate::machine::constants; use cartesi_dave_arithmetic as arithmetic; use cartesi_dave_merkle::Digest; +use cartesi_machine::types::cmio::CmioResponseReason; +use cartesi_machine::types::LogType; use cartesi_machine::{ - configuration::RuntimeConfig, - htif, - log::{AccessLog, AccessLogType}, - machine::Machine, + config::runtime::RuntimeConfig, machine::Machine, types::access_proof::AccessLog, }; use log::{debug, trace}; @@ -48,19 +47,19 @@ pub struct MachineInstance { impl MachineInstance { pub fn new(snapshot_path: &str) -> Result { - let mut machine = Machine::load(&Path::new(snapshot_path), RuntimeConfig::default())?; + let mut machine = Machine::load(Path::new(snapshot_path), &RuntimeConfig::default())?; - let root_hash = machine.get_root_hash()?; - let start_cycle = machine.read_mcycle()?; + let root_hash = machine.root_hash()?; + let start_cycle = machine.mcycle()?; // Machine can never be advanced on the micro arch. // Validators must verify this first - assert_eq!(machine.read_uarch_cycle()?, 0); + assert_eq!(machine.ucycle()?, 0); Ok(MachineInstance { machine, start_cycle, - root_hash: Digest::from_digest(root_hash.as_bytes())?, + root_hash: Digest::from_digest(&root_hash)?, cycle: 0, ucycle: 0, }) @@ -84,15 +83,15 @@ impl MachineInstance { // load inner machine with snapshot, update cycle, keep everything else the same pub fn load_snapshot(&mut self, snapshot_path: &Path, snapshot_cycle: u64) -> Result<()> { - let machine = Machine::load(&Path::new(snapshot_path), RuntimeConfig::default())?; + let mut machine = Machine::load(Path::new(snapshot_path), &RuntimeConfig::default())?; - let cycle = machine.read_mcycle()?; + let cycle = machine.mcycle()?; // Machine can not go backward behind the initial machine assert!(cycle >= self.start_cycle); self.cycle = snapshot_cycle; - assert_eq!(machine.read_uarch_cycle()?, 0); + assert_eq!(machine.ucycle()?, 0); self.machine = machine; @@ -112,12 +111,6 @@ impl MachineInstance { ucycle: u64, db: &ComputeStateAccess, ) -> Result { - let log_type = AccessLogType { - annotations: true, - proofs: true, - large_data: false, - }; - let mut logs = Vec::new(); let mut encode_input = None; if db.handle_rollups { @@ -139,24 +132,21 @@ impl MachineInstance { // need to process input if ucycle == 0 { let cmio_logs = self.machine.log_send_cmio_response( - htif::fromhost::ADVANCE_STATE, - &data, - log_type, - false, + CmioResponseReason::Advance, + data, + LogType::LargeData, )?; // append step logs to cmio logs - let step_logs = self.machine.log_uarch_step(log_type, false)?; + let step_logs = self.machine.log_step_uarch(LogType::LargeData)?; logs.push(&cmio_logs); logs.push(&step_logs); - return Ok(encode_access_logs(logs, Some(Input { 0: data.clone() }))); + return Ok(encode_access_logs(logs, Some(Input(data.clone())))); } else { self.machine - .send_cmio_response(htif::fromhost::ADVANCE_STATE, &data)?; - } - } else { - if ucycle == 0 { - encode_input = Some(Input { 0: Vec::new() }); + .send_cmio_response(CmioResponseReason::Advance, data)?; } + } else if ucycle == 0 { + encode_input = Some(Input(Vec::new())); } } } else { @@ -166,11 +156,11 @@ impl MachineInstance { self.run_uarch(ucycle)?; if ucycle == constants::UARCH_SPAN { - let reset_logs = self.machine.log_uarch_reset(log_type, false)?; + let reset_logs = self.machine.log_reset_uarch(LogType::LargeData)?; logs.push(&reset_logs); Ok(encode_access_logs(logs, encode_input)) } else { - let step_logs = self.machine.log_uarch_step(log_type, false)?; + let step_logs = self.machine.log_step_uarch(LogType::LargeData)?; logs.push(&step_logs); Ok(encode_access_logs(logs, encode_input)) } @@ -180,25 +170,25 @@ impl MachineInstance { pub fn run(&mut self, cycle: u64) -> Result { assert!(self.cycle <= cycle); - let mcycle = self.machine.read_mcycle()?; + let mcycle = self.machine.mcycle()?; let physical_cycle = arithmetic::add_and_clamp(mcycle, cycle - self.cycle); trace!("physical cycle {}", physical_cycle); loop { - let halted = self.machine.read_iflags_h()?; + let halted = self.machine.iflags_h()?; if halted { trace!("run break with halt"); break; } - let yielded = self.machine.read_iflags_y()?; + let yielded = self.machine.iflags_y()?; if yielded { trace!("run break with yield"); break; } - if self.machine.read_mcycle()? == physical_cycle { + if self.machine.mcycle()? == physical_cycle { trace!("run break with meeting physical cycle"); break; } @@ -208,7 +198,7 @@ impl MachineInstance { self.cycle = cycle; - Ok(self.machine_state()?) + self.machine_state() } pub fn run_uarch(&mut self, ucycle: u64) -> Result<()> { @@ -255,7 +245,7 @@ impl MachineInstance { trace!("run to next input cycle: {}", next_input_cycle); machine_state_without_input = self.run(next_input_cycle)?; if next_input_cycle == cycle { - self.take_snapshot(next_input_cycle, &db)?; + self.take_snapshot(next_input_cycle, db)?; } let input = inputs.get(next_input_index as usize); @@ -267,7 +257,7 @@ impl MachineInstance { trace!("input: 0x{}", data.encode_hex()); self.machine - .send_cmio_response(htif::fromhost::ADVANCE_STATE, data)?; + .send_cmio_response(CmioResponseReason::Advance, data)?; trace!( "after input, machine state: {}", @@ -280,7 +270,7 @@ impl MachineInstance { } if cycle > self.cycle { machine_state_without_input = self.run(cycle)?; - self.take_snapshot(cycle, &db)?; + self.take_snapshot(cycle, db)?; } Ok(machine_state_without_input) } @@ -288,24 +278,24 @@ impl MachineInstance { pub fn increment_uarch(&mut self) -> Result { self.machine.run_uarch(self.ucycle + 1)?; self.ucycle += 1; - Ok(self.machine_state()?) + self.machine_state() } pub fn ureset(&mut self) -> Result { self.machine.reset_uarch()?; self.cycle += 1; self.ucycle = 0; - Ok(self.machine_state()?) + self.machine_state() } pub fn machine_state(&mut self) -> Result { - let root_hash = self.machine.get_root_hash()?; - let halted = self.machine.read_iflags_h()?; - let yielded = self.machine.read_iflags_y()?; - let uhalted = self.machine.read_uarch_halt_flag()?; + let root_hash = self.machine.root_hash()?; + let halted = self.machine.iflags_h()?; + let yielded = self.machine.iflags_y()?; + let uhalted = self.machine.uarch_halt_flag()?; Ok(MachineState { - root_hash: Digest::from_digest(root_hash.as_bytes())?, + root_hash: Digest::from_digest(&root_hash)?, halted, yielded, uhalted, @@ -318,8 +308,8 @@ impl MachineInstance { Ok(()) } - pub fn position(&self) -> Result<(u64, u64, u64)> { - Ok((self.cycle, self.ucycle, self.machine.read_mcycle()?)) + pub fn position(&mut self) -> Result<(u64, u64, u64)> { + Ok((self.cycle, self.ucycle, self.machine.mcycle()?)) } } @@ -328,23 +318,25 @@ fn encode_access_logs(logs: Vec<&AccessLog>, encode_input: Option) -> Vec if let Some(i) = encode_input { encoded.push(U256::from(i.0.len()).to_be_bytes_vec()); - if i.0.len() > 0 { + if !i.0.is_empty() { encoded.push(i.0); } } for log in logs.iter() { - for a in log.accesses().iter() { - if a.log2_size() == 3 { - encoded.push(a.read_data().to_vec()); + for a in log.accesses.iter() { + if a.log2_size == 3 { + encoded.push(a.read.clone().unwrap()); } else { - encoded.push(a.read_hash().as_bytes().to_vec()); + encoded.push(a.read_hash.to_vec()); } let decoded_siblings: Vec> = a - .sibling_hashes() + .sibling_hashes + .clone() + .unwrap() .iter() - .map(|h| h.as_bytes().to_vec()) + .map(|h| h.to_vec()) .collect(); encoded.extend_from_slice(&decoded_siblings); }