From 7026c297e411c61309995e43e60266408db5a080 Mon Sep 17 00:00:00 2001 From: Mateusz Chudkowski Date: Thu, 29 Jan 2026 14:19:55 +0100 Subject: [PATCH 1/5] update celestia client, and fetch chain id from network --- Cargo.lock | 490 ++++++-------------- Cargo.toml | 4 +- bin/saya/src/sovereign.rs | 18 +- saya/core/src/data_availability/celestia.rs | 15 +- 4 files changed, 170 insertions(+), 357 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8e0b6ec..ae325eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -66,16 +57,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "alloy-rlp" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" -dependencies = [ - "arrayvec", - "bytes", -] - [[package]] name = "android_system_properties" version = "0.1.5" @@ -283,24 +264,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - [[package]] name = "ark-ff" version = "0.4.2" @@ -317,7 +280,7 @@ dependencies = [ "num-bigint", "num-traits", "paste", - "rustc_version 0.4.1", + "rustc_version", "zeroize", ] @@ -341,16 +304,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "ark-ff-asm" version = "0.4.2" @@ -371,18 +324,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "quote", - "syn 1.0.109", -] - [[package]] name = "ark-ff-macros" version = "0.4.2" @@ -481,16 +422,6 @@ dependencies = [ "ark-std 0.5.0", ] -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - [[package]] name = "ark-serialize" version = "0.4.2" @@ -538,16 +469,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - [[package]] name = "ark-std" version = "0.4.0" @@ -746,6 +667,28 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "async-task" version = "4.7.1" @@ -795,21 +738,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base-x" version = "0.2.11" @@ -1005,7 +933,7 @@ dependencies = [ "rand 0.8.5", "rstest", "rstest_reuse", - "semver 1.0.27", + "semver", "serde", "serde_json", "sha2 0.10.9", @@ -1052,14 +980,14 @@ dependencies = [ [[package]] name = "blockstore" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a8962daed8fb337472d9c4215006443acba1e40c6c91c9d4a3f440d1fb30436" +checksum = "509096e88e431095763b3f5ee1e1cdb09212e4d5b2eccc91ddea965deefedb7d" dependencies = [ "cid", "dashmap", "multihash", - "thiserror 1.0.69", + "thiserror 2.0.16", ] [[package]] @@ -1221,7 +1149,7 @@ dependencies = [ "indoc", "rayon", "rust-analyzer-salsa", - "semver 1.0.27", + "semver", "smol_str", "thiserror 2.0.16", ] @@ -1288,7 +1216,7 @@ dependencies = [ "cairo-lang-utils", "path-clean", "rust-analyzer-salsa", - "semver 1.0.27", + "semver", "serde", "smol_str", "toml", @@ -1756,9 +1684,9 @@ dependencies = [ [[package]] name = "celestia-proto" -version = "0.6.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71c3cf9caaf35a7530ea5ac2bab226c9e5c1bad3d661d3527a3951d6f80cbcc" +checksum = "65013505b04171f213d833b92bb076e9f229c36e5d144cb2faf25378397e2597" dependencies = [ "bytes", "prost", @@ -1772,25 +1700,35 @@ dependencies = [ [[package]] name = "celestia-rpc" -version = "0.8.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0970073d9e74fc74a417c5157146bbc122462c1dc7b2d5c442fe0b67be40e2cb" +checksum = "71f5f1ededb6d3398c6f922ad543594b0706d2de19e02d97024037cb750dbd89" dependencies = [ - "async-trait", + "async-stream", + "base64 0.22.1", + "celestia-proto", "celestia-types", + "futures-util", + "gloo-net", + "gloo-timers", "http 1.3.1", "jsonrpsee", - "prost", + "send_wrapper", "serde", - "thiserror 1.0.69", + "serde_json", + "serde_repr", + "tendermint-proto", + "thiserror 2.0.16", + "tokio", "tracing", + "web-sys", ] [[package]] name = "celestia-types" -version = "0.9.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70717cd176178cb3feb43795dd40a6a29ad5e48fae4222d8ba45182b93acbae" +checksum = "0fe616393f4c88756ed6b8097167a623c6e4e48e2a3d75109e3ea5d5941587e0" dependencies = [ "base64 0.22.1", "bech32", @@ -1801,16 +1739,20 @@ dependencies = [ "cid", "const_format", "enum_dispatch", + "getrandom 0.2.16", + "k256", "leopard-codec", + "lumina-utils", "multihash", "nmt-rs", "prost", - "ruint", + "rust_decimal", "serde", + "serde_repr", "sha2 0.10.9", "tendermint", "tendermint-proto", - "thiserror 1.0.69", + "thiserror 2.0.16", "time", ] @@ -2370,7 +2312,7 @@ dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", - "rustc_version 0.4.1", + "rustc_version", "syn 2.0.106", ] @@ -2769,28 +2711,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "fastrlp" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - [[package]] name = "ff" version = "0.13.1" @@ -3129,12 +3049,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.3" @@ -3154,6 +3068,23 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "gloo-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" +dependencies = [ + "gloo-utils", + "http 1.3.1", + "js-sys", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "gloo-timers" version = "0.3.0" @@ -3166,6 +3097,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "good_lp" version = "1.14.0" @@ -3813,17 +3757,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -3946,9 +3879,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.24.9" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b26c20e2178756451cfeb0661fb74c47dd5988cb7e3939de7e9241fd604d42" +checksum = "3f3f48dc3e6b8bd21e15436c1ddd0bc22a6a54e8ec46fedd6adf3425f396ec6a" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -3960,9 +3893,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.24.9" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bacb85abf4117092455e1573625e21b8f8ef4dec8aff13361140b2dc266cdff2" +checksum = "cf36eb27f8e13fa93dcb50ccb44c417e25b818cfa1a481b5470cd07b19c60b98" dependencies = [ "base64 0.22.1", "futures-util", @@ -3973,7 +3906,7 @@ dependencies = [ "rustls-pki-types", "rustls-platform-verifier", "soketto", - "thiserror 1.0.69", + "thiserror 2.0.16", "tokio", "tokio-rustls", "tokio-util", @@ -3983,9 +3916,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.24.9" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456196007ca3a14db478346f58c7238028d55ee15c1df15115596e411ff27925" +checksum = "316c96719901f05d1137f19ba598b5fe9c9bc39f4335f67f6be8613921946480" dependencies = [ "async-trait", "bytes", @@ -3999,19 +3932,19 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.16", "tokio", "tokio-stream", + "tower", "tracing", ] [[package]] name = "jsonrpsee-http-client" -version = "0.24.9" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c872b6c9961a4ccc543e321bb5b89f6b2d2c7fe8b61906918273a3333c95400c" +checksum = "790bedefcec85321e007ff3af84b4e417540d5c87b3c9779b9e247d1bcc3dab8" dependencies = [ - "async-trait", "base64 0.22.1", "http-body 1.0.1", "hyper 1.7.0", @@ -4023,18 +3956,17 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.16", "tokio", - "tower 0.4.13", - "tracing", + "tower", "url", ] [[package]] name = "jsonrpsee-proc-macros" -version = "0.24.9" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e65763c942dfc9358146571911b0cd1c361c2d63e2d2305622d40d36376ca80" +checksum = "2da3f8ab5ce1bb124b6d082e62dffe997578ceaf0aeb9f3174a214589dc00f07" dependencies = [ "heck 0.5.0", "proc-macro-crate", @@ -4045,26 +3977,27 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.24.9" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a8e70baf945b6b5752fc8eb38c918a48f1234daf11355e07106d963f860089" +checksum = "bc88ff4688e43cc3fa9883a8a95c6fa27aa2e76c96e610b737b6554d650d7fd5" dependencies = [ "http 1.3.1", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.16", ] [[package]] name = "jsonrpsee-ws-client" -version = "0.24.9" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b3323d890aa384f12148e8d2a1fd18eb66e9e7e825f9de4fa53bcc19b93eef" +checksum = "9b6fceceeb05301cc4c065ab3bd2fa990d41ff4eb44e4ca1b30fa99c057c3e79" dependencies = [ "http 1.3.1", "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", + "tower", "url", ] @@ -4077,7 +4010,9 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", + "once_cell", "sha2 0.10.9", + "signature", ] [[package]] @@ -4189,13 +4124,12 @@ dependencies = [ [[package]] name = "leopard-codec" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee58dbc414bd23885d7da915e0457618b36d1fc950a6169ef2cb29829d1b1a1d" +checksum = "3b397c7217467c5e5582fe413bc2f0e9f804367af8bc0f0374dc966f99d00f9c" dependencies = [ "bytes", - "lazy_static", - "thiserror 1.0.69", + "thiserror 2.0.16", ] [[package]] @@ -4271,18 +4205,18 @@ dependencies = [ [[package]] name = "logos" -version = "0.14.4" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458" +checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" dependencies = [ "logos-derive", ] [[package]] name = "logos-codegen" -version = "0.14.4" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f" +checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" dependencies = [ "beef", "fnv", @@ -4290,14 +4224,15 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax", + "rustc_version", "syn 2.0.106", ] [[package]] name = "logos-derive" -version = "0.14.4" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d" +checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" dependencies = [ "logos-codegen", ] @@ -4317,6 +4252,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lumina-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e68ba51207213b3fa8a42465526efdbe6c3c983a78a2a972d3a8e94d2bf9ab8" +dependencies = [ + "js-sys", +] + [[package]] name = "match-lookup" version = "0.1.1" @@ -4753,15 +4697,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -5008,16 +4943,6 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" -[[package]] -name = "pest" -version = "2.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" -dependencies = [ - "memchr", - "ucd-trie", -] - [[package]] name = "petgraph" version = "0.7.1" @@ -5331,22 +5256,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proptest" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" -dependencies = [ - "bitflags 2.9.4", - "lazy_static", - "num-traits", - "rand 0.9.2", - "rand_chacha 0.9.0", - "rand_xorshift", - "regex-syntax", - "unarray", -] - [[package]] name = "prost" version = "0.13.5" @@ -5392,13 +5301,12 @@ dependencies = [ [[package]] name = "prost-reflect" -version = "0.14.7" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5edd582b62f5cde844716e66d92565d7faf7ab1445c8cebce6e00fba83ddb2" +checksum = "37587d5a8a1b3dc9863403d084fc2254b91ab75a702207098837950767e2260b" dependencies = [ "logos", "miette", - "once_cell", "prost", "prost-types", ] @@ -5414,9 +5322,9 @@ dependencies = [ [[package]] name = "protox" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f352af331bf637b8ecc720f7c87bf903d2571fa2e14a66e9b2558846864b54a" +checksum = "424c2bd294b69c49b949f3619362bc3c5d28298cd1163b6d1a62df37c16461aa" dependencies = [ "bytes", "miette", @@ -5424,19 +5332,19 @@ dependencies = [ "prost-reflect", "prost-types", "protox-parse", - "thiserror 1.0.69", + "thiserror 2.0.16", ] [[package]] name = "protox-parse" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a462d115462c080ae000c29a47f0b3985737e5d3a995fcdbcaa5c782068dde" +checksum = "57927f9dbeeffcce7192404deee6157a640cbb3fe8ac11eabbe571565949ab75" dependencies = [ "logos", "miette", "prost-types", - "thiserror 1.0.69", + "thiserror 2.0.16", ] [[package]] @@ -5574,15 +5482,6 @@ dependencies = [ "getrandom 0.3.3", ] -[[package]] -name = "rand_xorshift" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" -dependencies = [ - "rand_core 0.9.3", -] - [[package]] name = "rawpointer" version = "0.2.1" @@ -5743,7 +5642,7 @@ dependencies = [ "sync_wrapper 1.0.2", "tokio", "tokio-rustls", - "tower 0.5.2", + "tower", "tower-http", "tower-service", "url", @@ -5852,7 +5751,7 @@ dependencies = [ "futures", "futures-timer", "rstest_macros", - "rustc_version 0.4.1", + "rustc_version", ] [[package]] @@ -5864,7 +5763,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "rustc_version 0.4.1", + "rustc_version", "syn 1.0.109", "unicode-ident", ] @@ -5880,40 +5779,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "ruint" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "ark-ff 0.5.0", - "bytes", - "fastrlp 0.3.1", - "fastrlp 0.4.0", - "num-bigint", - "num-integer", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand 0.8.5", - "rand 0.9.2", - "rlp", - "ruint-macro", - "serde_core", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" - [[package]] name = "rust-analyzer-salsa" version = "0.17.0-pre.6" @@ -5951,14 +5816,9 @@ checksum = "c8975fc98059f365204d635119cf9c5a60ae67b841ed49b5422a9a7e56cdfac0" dependencies = [ "arrayvec", "num-traits", + "serde", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -5977,22 +5837,13 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.27", + "semver", ] [[package]] @@ -6314,15 +6165,6 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.27" @@ -6334,12 +6176,12 @@ dependencies = [ ] [[package]] -name = "semver-parser" -version = "0.10.3" +name = "send_wrapper" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" dependencies = [ - "pest", + "futures-core", ] [[package]] @@ -7187,7 +7029,7 @@ dependencies = [ "pretty_assertions", "primitive-types", "rand 0.8.5", - "semver 1.0.27", + "semver", "serde", "serde_json", "sha3", @@ -7781,29 +7623,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", "socket2 0.6.0", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.0", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -7926,21 +7765,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower" version = "0.5.2" @@ -7969,7 +7793,7 @@ dependencies = [ "http-body 1.0.1", "iri-string", "pin-project-lite", - "tower 0.5.2", + "tower", "tower-layer", "tower-service", ] @@ -8121,12 +7945,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - [[package]] name = "uint" version = "0.9.5" @@ -8139,12 +7957,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - [[package]] name = "unescaper" version = "0.1.6" diff --git a/Cargo.toml b/Cargo.toml index eef72e9..6931a2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,8 +23,8 @@ starknet_api = { git = "https://github.com/karnotxyz/sequencer", rev = "e04617e0 anyhow = { version = "1.0.95", default-features = false } bigdecimal = { version = "0.3.1", default-features = false } cairo-vm = "=2.5.0" -celestia-rpc = { version = "0.8.0", default-features = false } -celestia-types = { version = "0.9.0", default-features = false } +celestia-rpc = { version = "0.16.2", default-features = false } +celestia-types = { version = "0.20.0", default-features = false } ciborium = { version = "0.2.2", default-features = false } clap = { version = "4.5.23", default-features = false, features = ["derive", "env", "std"] } env_logger = {version = "0.11.6",features = ["unstable-kv"]} diff --git a/bin/saya/src/sovereign.rs b/bin/saya/src/sovereign.rs index 6738b07..b925a8b 100644 --- a/bin/saya/src/sovereign.rs +++ b/bin/saya/src/sovereign.rs @@ -1,4 +1,4 @@ -use std::{io::Read, path::PathBuf, time::Duration}; +use std::{path::PathBuf, time::Duration}; use anyhow::Result; use clap::{Parser, Subcommand}; @@ -11,6 +11,7 @@ use saya_core::{ storage::{InMemoryStorageBackend, SqliteDb}, ChainId, OsHintsConfiguration, }; +use starknet::{core::utils::parse_cairo_short_string, providers::{JsonRpcClient, Provider, jsonrpc::HttpTransport}}; use url::Url; use crate::common::{calculate_workers_per_stage, SAYA_DB_PATH}; @@ -35,9 +36,6 @@ struct Start { /// Starknet JSON-RPC URL (v0.7.1) #[clap(long, env)] starknet_rpc: Url, - /// Path to the compiled Starknet OS program - #[clap(long, env)] - snos_program: PathBuf, /// Whether to mock the SNOS proof by extracting the output from the PIE and using it from a proof. #[clap(long)] mock_snos_from_pie: bool, @@ -97,10 +95,6 @@ impl Sovereign { impl Start { pub async fn run(self) -> Result<()> { - let mut snos_file = std::fs::File::open(self.snos_program)?; - let mut snos = Vec::with_capacity(snos_file.metadata()?.len() as usize); - snos_file.read_to_end(&mut snos)?; - let saya_path = self .db_dir .map(|db_dir| format!("{}/{}", db_dir.display(), SAYA_DB_PATH)) @@ -111,6 +105,12 @@ impl Start { calculate_workers_per_stage(self.blocks_processed_in_parallel); let [snos_worker_count, _layout_bridge_workers_count, ingestor_worker_count] = workers_distribution; + + let chain_id = parse_cairo_short_string( + &JsonRpcClient::new(HttpTransport::new(self.starknet_rpc.clone())) + .chain_id() + .await?, + )?; let block_ingestor_builder = PollingBlockIngestorBuilder::new( self.starknet_rpc, @@ -121,7 +121,7 @@ impl Start { full_output: false, use_kzg_da: false, }, - ChainId::Other("KATANA3".to_string()), + ChainId::Other(chain_id), ); let prover_builder = AtlanticSnosProverBuilder::new( diff --git a/saya/core/src/data_availability/celestia.rs b/saya/core/src/data_availability/celestia.rs index 8693129..03639c2 100644 --- a/saya/core/src/data_availability/celestia.rs +++ b/saya/core/src/data_availability/celestia.rs @@ -1,6 +1,6 @@ use anyhow::Result; -use celestia_rpc::{BlobClient, Client}; -use celestia_types::{nmt::Namespace, AppVersion, Blob, TxConfig}; +use celestia_rpc::{BlobClient, Client, TxConfig}; +use celestia_types::{nmt::Namespace, AppVersion, Blob, }; use log::{debug, info}; use tokio::sync::mpsc::{Receiver, Sender}; use url::Url; @@ -53,7 +53,7 @@ where debug!("Received new proof"); // TODO: error handling - let client = Client::new(self.rpc_url.as_ref(), Some(&self.auth_token)) + let client = Client::new(self.rpc_url.as_ref(), Some(&self.auth_token),None,None) .await .unwrap(); @@ -68,8 +68,9 @@ where ciborium::into_writer(&packet, &mut serialized_packet).unwrap(); // TODO: error handling - let blob = Blob::new(self.namespace, serialized_packet, AppVersion::V3).unwrap(); - let commitment = blob.commitment.0; + let blob = Blob::new(self.namespace, serialized_packet, None,AppVersion::latest()).unwrap(); + let commitment = blob.clone().commitment; + let commitment = commitment.hash(); let tx_config = TxConfig { key_name: self.key_name.clone(), @@ -88,7 +89,7 @@ where self.last_pointer = Some(DataAvailabilityPointer { height: celestia_block, - commitment, + commitment: *commitment, }); info!( @@ -102,7 +103,7 @@ where block_number: new_proof.block_number(), pointer: Some(DataAvailabilityPointer { height: celestia_block, - commitment, + commitment: *commitment, }), full_payload: new_proof, }; From 8c559de733416608b14d218268d7268910516349 Mon Sep 17 00:00:00 2001 From: Mateusz Chudkowski Date: Thu, 29 Jan 2026 17:57:01 +0100 Subject: [PATCH 2/5] blob posting --- bin/saya/src/persistent.rs | 25 ++++++++++++- bin/saya/src/sovereign.rs | 9 +++-- saya/core/src/block_ingestor/mod.rs | 2 + saya/core/src/block_ingestor/polling.rs | 23 +++++++++++- saya/core/src/data_availability/celestia.rs | 14 +++++-- saya/core/src/data_availability/mod.rs | 5 ++- .../core/src/prover/atlantic/layout_bridge.rs | 5 ++- saya/core/src/prover/mock/layout_bridge.rs | 1 + saya/core/src/prover/mod.rs | 18 +++------ saya/core/src/storage/mod.rs | 12 ++++++ saya/core/src/storage/sql_lite/mod.rs | 15 ++++++++ saya/core/src/storage/sql_lite/storage.rs | 29 +++++++++++++++ saya/core/src/storage/sql_lite/utils.rs | 37 ++++++++++++++++++- 13 files changed, 168 insertions(+), 27 deletions(-) diff --git a/bin/saya/src/persistent.rs b/bin/saya/src/persistent.rs index 4883dc6..1b86bd2 100644 --- a/bin/saya/src/persistent.rs +++ b/bin/saya/src/persistent.rs @@ -4,7 +4,7 @@ use anyhow::Result; use clap::{Parser, Subcommand}; use saya_core::{ block_ingestor::PollingBlockIngestorBuilder, - data_availability::NoopDataAvailabilityBackendBuilder, + data_availability::CelestiaDataAvailabilityBackendBuilder, orchestrator::PersistentOrchestratorBuilder, prover::{ AtlanticLayoutBridgeProverBuilder, AtlanticSnosProverBuilder, @@ -25,6 +25,7 @@ use url::Url; use crate::{ any::AnyLayoutBridgeProverBuilder, common::{calculate_workers_per_stage, NUMBER_OF_STAGES, SAYA_DB_PATH}, + sovereign::validate_non_empty, }; /// 10 seconds. @@ -82,6 +83,19 @@ struct Start { /// Configuration for OS pie generation #[clap(flatten)] hints: HintsConfiguration, + #[clap(long, env)] + celestia_rpc: Url, + /// Celestia RPC node auth token + #[clap(long, env)] + celestia_token: String, + /// Celestia key name + #[clap(long, env)] + celestia_key_name: Option, + /// Celestia namespace + #[clap(long, env)] + #[clap(default_value = "sayaproofs")] + #[clap(value_parser = validate_non_empty)] + celestia_namespace: String, } #[derive(Debug, Parser, Clone)] @@ -185,7 +199,14 @@ impl Start { ), layout_bridge_prover_builder, ); - let da_builder = NoopDataAvailabilityBackendBuilder::new(); + let da_builder = CelestiaDataAvailabilityBackendBuilder::new( + self.celestia_rpc, + self.celestia_token, + self.celestia_namespace, + self.celestia_key_name, + ) + .unwrap(); + let settlement_builder = PiltoverSettlementBackendBuilder::new( self.settlement_rpc, self.settlement_piltover_address, diff --git a/bin/saya/src/sovereign.rs b/bin/saya/src/sovereign.rs index b925a8b..39482bc 100644 --- a/bin/saya/src/sovereign.rs +++ b/bin/saya/src/sovereign.rs @@ -11,7 +11,10 @@ use saya_core::{ storage::{InMemoryStorageBackend, SqliteDb}, ChainId, OsHintsConfiguration, }; -use starknet::{core::utils::parse_cairo_short_string, providers::{JsonRpcClient, Provider, jsonrpc::HttpTransport}}; +use starknet::{ + core::utils::parse_cairo_short_string, + providers::{jsonrpc::HttpTransport, JsonRpcClient, Provider}, +}; use url::Url; use crate::common::{calculate_workers_per_stage, SAYA_DB_PATH}; @@ -68,7 +71,7 @@ struct Start { } /// Validate that the value is not empty. -fn validate_non_empty(s: &str) -> Result { +pub fn validate_non_empty(s: &str) -> Result { if s.trim().is_empty() { Err("Value cannot be empty".to_string()) } else { @@ -105,7 +108,7 @@ impl Start { calculate_workers_per_stage(self.blocks_processed_in_parallel); let [snos_worker_count, _layout_bridge_workers_count, ingestor_worker_count] = workers_distribution; - + let chain_id = parse_cairo_short_string( &JsonRpcClient::new(HttpTransport::new(self.starknet_rpc.clone())) .chain_id() diff --git a/saya/core/src/block_ingestor/mod.rs b/saya/core/src/block_ingestor/mod.rs index 087392c..121cbd0 100644 --- a/saya/core/src/block_ingestor/mod.rs +++ b/saya/core/src/block_ingestor/mod.rs @@ -1,5 +1,6 @@ use anyhow::Result; +use starknet::core::types::StateUpdate; use tokio::sync::mpsc::Sender; mod polling; @@ -24,4 +25,5 @@ pub trait BlockIngestor: Daemon {} pub struct BlockInfo { pub number: u64, pub status: BlockStatus, + pub state_update: Option, } diff --git a/saya/core/src/block_ingestor/polling.rs b/saya/core/src/block_ingestor/polling.rs index bb242d2..2b8c5b0 100644 --- a/saya/core/src/block_ingestor/polling.rs +++ b/saya/core/src/block_ingestor/polling.rs @@ -7,7 +7,10 @@ use generate_pie::{ types::{ChainConfig, OsHintsConfiguration}, }; use log::{debug, error, info, trace}; -use starknet::providers::{jsonrpc::HttpTransport, JsonRpcClient, Provider}; +use starknet::{ + core::types::BlockId, + providers::{jsonrpc::HttpTransport, JsonRpcClient, Provider}, +}; use starknet_api::{contract_address, core::ChainId}; use tokio::{ sync::{ @@ -106,6 +109,22 @@ where db.initialize_block(block_number.try_into().unwrap()) .await .unwrap(); + let state_update = &JsonRpcClient::new(HttpTransport::new(rpc_url.clone())) + .get_state_update(BlockId::Number(block_number)) + .await + .unwrap(); + let state_update = match state_update { + starknet::core::types::MaybePreConfirmedStateUpdate::Update(state_update) => { + state_update + } + starknet::core::types::MaybePreConfirmedStateUpdate::PreConfirmedUpdate(_) => { + panic!("PreConfirmedStateUpdate not supported") + } + }; + + db.add_state_update(block_number.try_into().unwrap(), state_update.clone()) + .await + .unwrap(); match db .get_pie(block_number.try_into().unwrap(), Step::Snos) @@ -116,6 +135,7 @@ where let new_block = BlockInfo { number: block_number, status: BlockStatus::SnosPieGenerated, + state_update: Some(state_update.clone()), }; trace!(block_number; "Pie generated"); @@ -159,6 +179,7 @@ where let new_block = BlockInfo { number: block_number, status: BlockStatus::SnosPieGenerated, + state_update: None, }; let pie_bytes = compress_pie(pie.clone()).await.unwrap(); diff --git a/saya/core/src/data_availability/celestia.rs b/saya/core/src/data_availability/celestia.rs index 03639c2..f02fed7 100644 --- a/saya/core/src/data_availability/celestia.rs +++ b/saya/core/src/data_availability/celestia.rs @@ -1,6 +1,6 @@ use anyhow::Result; use celestia_rpc::{BlobClient, Client, TxConfig}; -use celestia_types::{nmt::Namespace, AppVersion, Blob, }; +use celestia_types::{nmt::Namespace, AppVersion, Blob}; use log::{debug, info}; use tokio::sync::mpsc::{Receiver, Sender}; use url::Url; @@ -53,7 +53,7 @@ where debug!("Received new proof"); // TODO: error handling - let client = Client::new(self.rpc_url.as_ref(), Some(&self.auth_token),None,None) + let client = Client::new(self.rpc_url.as_ref(), Some(&self.auth_token), None, None) .await .unwrap(); @@ -68,7 +68,13 @@ where ciborium::into_writer(&packet, &mut serialized_packet).unwrap(); // TODO: error handling - let blob = Blob::new(self.namespace, serialized_packet, None,AppVersion::latest()).unwrap(); + let blob = Blob::new( + self.namespace, + serialized_packet, + None, + AppVersion::latest(), + ) + .unwrap(); let commitment = blob.clone().commitment; let commitment = commitment.hash(); @@ -132,7 +138,7 @@ impl

CelestiaDataAvailabilityBackendBuilder

{ auth_token, namespace: Namespace::new_v0(namespace.as_bytes())?, key_name, - last_pointer: None, + last_pointer: Some(None), proof_channel: None, cursor_channel: None, }) diff --git a/saya/core/src/data_availability/mod.rs b/saya/core/src/data_availability/mod.rs index b851ac9..7f61ae6 100644 --- a/saya/core/src/data_availability/mod.rs +++ b/saya/core/src/data_availability/mod.rs @@ -1,5 +1,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; +use starknet::core::types::StateUpdate; use swiftness_stark::types::StarkProof; use tokio::sync::mpsc::{Receiver, Sender}; @@ -74,7 +75,9 @@ pub struct SovereignPacket { /// the state diff section) needs to be made available anyway, so we might as well just keep the DA /// posting mechanism in place for now. #[derive(Debug, Serialize, Deserialize)] -pub struct PersistentPacket; +pub struct PersistentPacket { + pub state_update: StateUpdate, +} // TODO: abstract over this to allow other DA backends. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] diff --git a/saya/core/src/prover/atlantic/layout_bridge.rs b/saya/core/src/prover/atlantic/layout_bridge.rs index ed6c992..c582ac4 100644 --- a/saya/core/src/prover/atlantic/layout_bridge.rs +++ b/saya/core/src/prover/atlantic/layout_bridge.rs @@ -67,7 +67,7 @@ where }; let block_number_u32 = new_snos_proof.block_number.try_into().unwrap(); - + let state_update = db.get_state_update(block_number_u32).await.unwrap(); match db .get_proof(block_number_u32, crate::storage::Step::Bridge) .await @@ -85,6 +85,7 @@ where let block_info = BlockInfo { number: new_snos_proof.block_number, status: crate::storage::BlockStatus::SnosProofGenerated, + state_update: Some(state_update.clone()), }; task_tx.send(block_info).await.unwrap(); @@ -155,6 +156,7 @@ where let new_proof = BlockInfo { number: new_snos_proof.block_number, status: crate::storage::BlockStatus::SnosProofGenerated, + state_update: Some(state_update.clone()), }; task_tx.send(new_proof).await.unwrap(); @@ -325,6 +327,7 @@ where let new_proof = BlockInfo { number: new_snos_proof.block_number, status: crate::storage::BlockStatus::SnosProofGenerated, + state_update: Some(state_update.clone()), }; tokio::select! { diff --git a/saya/core/src/prover/mock/layout_bridge.rs b/saya/core/src/prover/mock/layout_bridge.rs index b0b3b9a..5d14214 100644 --- a/saya/core/src/prover/mock/layout_bridge.rs +++ b/saya/core/src/prover/mock/layout_bridge.rs @@ -104,6 +104,7 @@ where let new_proof = BlockInfo { number: new_proof.block_number, status: crate::storage::BlockStatus::BridgeProofGenerated, + state_update: None, }; tokio::select! { _ = self.finish_handle.shutdown_requested() => break, diff --git a/saya/core/src/prover/mod.rs b/saya/core/src/prover/mod.rs index 53add56..bbee4b1 100644 --- a/saya/core/src/prover/mod.rs +++ b/saya/core/src/prover/mod.rs @@ -73,18 +73,6 @@ impl DataAvailabilityPayload for SnosProof { } } -impl DataAvailabilityPayload for RecursiveProof { - type Packet = PersistentPacket; - - fn block_number(&self) -> u64 { - self.block_number - } - - fn into_packet(self, _ctx: DataAvailabilityPacketContext) -> Self::Packet { - PersistentPacket - } -} - impl DataAvailabilityPayload for BlockInfo { type Packet = PersistentPacket; @@ -93,6 +81,10 @@ impl DataAvailabilityPayload for BlockInfo { } fn into_packet(self, _ctx: DataAvailabilityPacketContext) -> Self::Packet { - PersistentPacket + if let Some(state_update) = self.state_update { + PersistentPacket { state_update } + } else { + panic!("BlockInfo must contain state_update to be converted into PersistentPacket"); + } } } diff --git a/saya/core/src/storage/mod.rs b/saya/core/src/storage/mod.rs index 4521280..dc1cc0f 100644 --- a/saya/core/src/storage/mod.rs +++ b/saya/core/src/storage/mod.rs @@ -1,5 +1,6 @@ use crate::data_availability::DataAvailabilityPointer; use anyhow::Result; +use starknet::core::types::StateUpdate; use std::future::Future; mod in_memory; @@ -154,4 +155,15 @@ pub trait PersistantStorage { &self, block_id: &[u32], ) -> impl Future> + Send; + + fn add_state_update( + &self, + block_number: u32, + state_update: StateUpdate, + ) -> impl Future> + Send; + + fn get_state_update( + &self, + block_number: u32, + ) -> impl Future> + Send; } diff --git a/saya/core/src/storage/sql_lite/mod.rs b/saya/core/src/storage/sql_lite/mod.rs index e707ac1..ca5bd19 100644 --- a/saya/core/src/storage/sql_lite/mod.rs +++ b/saya/core/src/storage/sql_lite/mod.rs @@ -49,6 +49,7 @@ impl SqliteDb { Self::create_pies_table(&pool).await?; Self::create_job_id_table(&pool).await?; Self::create_failed_blocks_table(&pool).await?; + Self::create_state_update_table(&pool).await?; } else { trace!("Table 'blocks' with correct structure found."); } @@ -144,4 +145,18 @@ impl SqliteDb { .await?; Ok(()) } + pub async fn create_state_update_table(pool: &Pool) -> Result<(), Error> { + query( + r#" + CREATE TABLE IF NOT EXISTS state_updates ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + block_id INTEGER NOT NULL, + state_update BLOB NOT NULL + ); + "#, + ) + .execute(pool) + .await?; + Ok(()) + } } diff --git a/saya/core/src/storage/sql_lite/storage.rs b/saya/core/src/storage/sql_lite/storage.rs index fefdd44..a20029f 100644 --- a/saya/core/src/storage/sql_lite/storage.rs +++ b/saya/core/src/storage/sql_lite/storage.rs @@ -305,6 +305,35 @@ impl PersistantStorage for SqliteDb { sql_query.execute(&self.pool).await?; Ok(()) } + + async fn add_state_update( + &self, + block_number: u32, + state_update: starknet::core::types::StateUpdate, + ) -> anyhow::Result<()> { + let serialized = serde_json::to_vec(&state_update)?; + let mut tx = self.pool.begin().await?; + query("INSERT OR IGNORE INTO state_updates (block_id, state_update) VALUES (?, ?);") + .bind(block_number) + .bind(serialized) + .execute(&mut *tx) + .await?; + tx.commit().await?; + Ok(()) + } + + async fn get_state_update( + &self, + block_number: u32, + ) -> anyhow::Result { + let row = query("SELECT state_update FROM state_updates WHERE block_id = ?1") + .bind(block_number) + .fetch_one(&self.pool) + .await?; + let serialized: Vec = row.try_get(0)?; + let state_update: starknet::core::types::StateUpdate = serde_json::from_slice(&serialized)?; + Ok(state_update) + } } #[cfg(test)] diff --git a/saya/core/src/storage/sql_lite/utils.rs b/saya/core/src/storage/sql_lite/utils.rs index fa77401..aa881b2 100644 --- a/saya/core/src/storage/sql_lite/utils.rs +++ b/saya/core/src/storage/sql_lite/utils.rs @@ -11,7 +11,13 @@ impl SqliteDb { let pies_table = Self::check_pies_table(pool).await?; let job_ids_table = Self::check_ids_table(pool).await?; let failed_blocks_table = Self::check_failed_blocks_table(pool).await?; - Ok(blocks_table && proofs_table && pies_table && job_ids_table && failed_blocks_table) + let state_updates_table = Self::check_state_updates_table(pool).await?; + Ok(blocks_table + && proofs_table + && pies_table + && job_ids_table + && failed_blocks_table + && state_updates_table) } /// Function to check if the blocks table has the correct columns @@ -133,9 +139,36 @@ impl SqliteDb { Ok(has_id && has_block_id && has_failure_reason) } + /// Function to check if the state_updates table has the correct columns + pub(crate) async fn check_state_updates_table(pool: &Pool) -> Result { + let columns = sqlx::query("PRAGMA table_info(state_updates);") + .fetch_all(pool) + .await?; + let mut has_id = false; + let mut has_block_id = false; + let mut has_state_update = false; + for column in columns { + let name: String = column.get("name"); + match name.as_str() { + "id" => has_id = true, + "block_id" => has_block_id = true, + "state_update" => has_state_update = true, + _ => {} + } + } + Ok(has_id && has_block_id && has_state_update) + } + /// Function to check if the tables exist pub(crate) async fn check_tables_exist(pool: &Pool) -> Result { - let expected_tables = vec!["blocks", "pies", "proofs", "job_ids", "failed_blocks"]; + let expected_tables = vec![ + "blocks", + "pies", + "proofs", + "job_ids", + "failed_blocks", + "state_updates", + ]; for table in expected_tables { let exists = sqlx::query("SELECT name FROM sqlite_master WHERE type='table' AND name=?") From 55a127e4c352cffeedda98b9a6aa92637d29e0d5 Mon Sep 17 00:00:00 2001 From: Mateusz Chudkowski Date: Fri, 30 Jan 2026 15:03:27 +0100 Subject: [PATCH 3/5] working e2e --- Cargo.lock | 157 +++++++++++++++++++++ Cargo.toml | 2 + bin/saya/src/persistent.rs | 1 + saya/core/Cargo.toml | 2 + saya/core/src/block_ingestor/mod.rs | 7 + saya/core/src/prover/mock/layout_bridge.rs | 8 +- saya/core/src/settlement/piltover.rs | 69 +++++---- 7 files changed, 219 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae325eb..f4ee15a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1113,6 +1113,110 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" +[[package]] +name = "cainome" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f296568cda6f1f4934270a321151f9f51afa737450f67ef13a8534f2bd9afdac" +dependencies = [ + "anyhow", + "async-trait", + "cainome-cairo-serde", + "cainome-cairo-serde-derive", + "cainome-parser", + "cainome-rs", + "cainome-rs-macro", + "camino", + "clap", + "clap_complete", + "convert_case 0.8.0", + "serde", + "serde_json", + "starknet", + "starknet-types-core 0.2.1", + "thiserror 2.0.16", + "tracing", + "tracing-subscriber", + "url", +] + +[[package]] +name = "cainome-cairo-serde" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ae2d4c21db23c7730a85187c2e9d73fe00c123171839185fb13f31550f3240" +dependencies = [ + "num-bigint", + "serde", + "serde_with", + "starknet", + "thiserror 2.0.16", +] + +[[package]] +name = "cainome-cairo-serde-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d272424141f0ced49ca5f40bc4b756235ee6e7c9cf6ab01f7ef5ac010f5f8864" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "unzip-n", +] + +[[package]] +name = "cainome-parser" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ffdbc6abfba9c7e91beb87fe7561f097d9f7bbda45c6ff74be3a9ff3f1a0124" +dependencies = [ + "convert_case 0.8.0", + "quote", + "serde_json", + "starknet", + "syn 2.0.106", + "thiserror 2.0.16", +] + +[[package]] +name = "cainome-rs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93aa5c33e66b58ff6723d3e43e60fe163ac20719ea89fce921096e654b15bcd6" +dependencies = [ + "anyhow", + "cainome-cairo-serde", + "cainome-parser", + "camino", + "prettyplease", + "proc-macro2", + "quote", + "serde_json", + "starknet", + "syn 2.0.106", + "thiserror 2.0.16", +] + +[[package]] +name = "cainome-rs-macro" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d679cd9a88b9d412ed4ed30264b80f1bec6c1aa9656e238f06be560ddebb652" +dependencies = [ + "anyhow", + "cainome-cairo-serde", + "cainome-parser", + "cainome-rs", + "proc-macro-error", + "proc-macro2", + "quote", + "serde_json", + "starknet", + "syn 2.0.106", + "thiserror 2.0.16", +] + [[package]] name = "cairo-lang-casm" version = "2.12.3" @@ -1672,6 +1776,15 @@ dependencies = [ "zip 0.6.6", ] +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +dependencies = [ + "serde_core", +] + [[package]] name = "cc" version = "1.2.38" @@ -1859,6 +1972,15 @@ dependencies = [ "strsim 0.11.1", ] +[[package]] +name = "clap_complete" +version = "4.5.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "430b4dc2b5e3861848de79627b2bedc9f3342c7da5173a14eaa5d0f8dc18ae5d" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "4.5.47" @@ -5001,6 +5123,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" +[[package]] +name = "piltover" +version = "0.1.0" +source = "git+https://github.com/cartridge-gg/piltover.git?branch=feat%2Fupdate-starknet-output#3edc066544587512141127c19f641ac6a8cd941a" +dependencies = [ + "cainome", + "starknet", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -6008,6 +6139,7 @@ version = "0.2.1" dependencies = [ "anyhow", "bigdecimal", + "cainome", "cairo-vm", "celestia-rpc", "celestia-types", @@ -6018,6 +6150,7 @@ dependencies = [ "integrity", "log", "num-traits", + "piltover", "reqwest 0.12.23", "serde", "serde_json", @@ -7854,6 +7987,16 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.20" @@ -7864,12 +8007,15 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex-automata", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] @@ -8035,6 +8181,17 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" +[[package]] +name = "unzip-n" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b5bb2756c16fb66f80cfbf5fb0e0c09a7001e739f453c9ec241b9c8b1556fda" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "url" version = "2.5.7" diff --git a/Cargo.toml b/Cargo.toml index 6931a2a..4cf3b7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,3 +54,5 @@ tokio-util = { version = "0.7.13", default-features = false } url = { version = "2.5.4", default-features = false } zip = { version = "2.2.2", default-features = false, features = ["deflate"] } sqlx = { version = "0.8.2", features = [ "chrono", "macros", "regexp", "runtime-async-std", "runtime-tokio", "sqlite", "uuid" ] } +piltover = {package = "piltover", git = "https://github.com/cartridge-gg/piltover.git", branch = "feat/update-starknet-output" } +cainome = { version = "0.10.1", features = ["abigen-rs"] } diff --git a/bin/saya/src/persistent.rs b/bin/saya/src/persistent.rs index 1b86bd2..bdc0000 100644 --- a/bin/saya/src/persistent.rs +++ b/bin/saya/src/persistent.rs @@ -83,6 +83,7 @@ struct Start { /// Configuration for OS pie generation #[clap(flatten)] hints: HintsConfiguration, + /// Celestia RPC endpoint URL #[clap(long, env)] celestia_rpc: Url, /// Celestia RPC node auth token diff --git a/saya/core/Cargo.toml b/saya/core/Cargo.toml index e307ff9..c8cef43 100644 --- a/saya/core/Cargo.toml +++ b/saya/core/Cargo.toml @@ -38,3 +38,5 @@ sqlx.workspace = true cairo-vm.workspace = true generate-pie.workspace = true starknet_api.workspace = true +piltover.workspace = true +cainome.workspace = true \ No newline at end of file diff --git a/saya/core/src/block_ingestor/mod.rs b/saya/core/src/block_ingestor/mod.rs index 121cbd0..f3558b4 100644 --- a/saya/core/src/block_ingestor/mod.rs +++ b/saya/core/src/block_ingestor/mod.rs @@ -27,3 +27,10 @@ pub struct BlockInfo { pub status: BlockStatus, pub state_update: Option, } + +#[derive(Debug, Clone)] +pub struct BlobPointer { + pub height: u64, + pub commitment: [u8; 32], + pub namespace: String, +} diff --git a/saya/core/src/prover/mock/layout_bridge.rs b/saya/core/src/prover/mock/layout_bridge.rs index 5d14214..b6edbf1 100644 --- a/saya/core/src/prover/mock/layout_bridge.rs +++ b/saya/core/src/prover/mock/layout_bridge.rs @@ -41,10 +41,14 @@ where _ = self.finish_handle.shutdown_requested() => break, new_snos_proof = self.statement_channel.recv() => new_snos_proof, }; - // This should be fine for now as block ingestors wouldn't drop senders. This might // change in the future. let new_snos_proof = new_snos_proof.unwrap(); + let state_update = self + .db + .get_state_update(new_snos_proof.block_number.try_into().unwrap()) + .await + .unwrap(); debug!( "Receive raw SNOS proof for block #{}", @@ -104,7 +108,7 @@ where let new_proof = BlockInfo { number: new_proof.block_number, status: crate::storage::BlockStatus::BridgeProofGenerated, - state_update: None, + state_update: Some(state_update), }; tokio::select! { _ = self.finish_handle.shutdown_requested() => break, diff --git a/saya/core/src/settlement/piltover.rs b/saya/core/src/settlement/piltover.rs index e514910..8dd8711 100644 --- a/saya/core/src/settlement/piltover.rs +++ b/saya/core/src/settlement/piltover.rs @@ -1,9 +1,3 @@ -use std::{ - collections::BTreeMap, - sync::Arc, - time::{Duration, Instant}, -}; - use crate::{ block_ingestor::BlockInfo, data_availability::DataAvailabilityCursor, @@ -15,10 +9,11 @@ use crate::{ use anyhow::Result; use integrity::{split_proof, VerifierConfiguration}; use log::{debug, info}; +use piltover::{DaLayerInfo, PiltoverInput}; use starknet::{ accounts::{Account, ConnectedAccount, SingleOwnerAccount}, core::{ - codec::{Decode, Encode}, + codec::Decode, types::{BlockId, BlockTag, Call, FunctionCall, TransactionReceipt}, }, macros::{selector, short_string}, @@ -26,6 +21,11 @@ use starknet::{ signers::{LocalWallet, SigningKey}, }; use starknet_types_core::felt::Felt; +use std::{ + collections::BTreeMap, + sync::Arc, + time::{Duration, Instant}, +}; use swiftness::types::StarkProof; use swiftness::TransformTo; use tokio::sync::mpsc::{Receiver, Sender}; @@ -67,11 +67,6 @@ struct AppchainState { block_hash: Felt, } -#[derive(Debug, Encode)] -struct UpdateStateCalldata { - program_output: Vec, -} - #[derive(Debug)] enum FactRegistrationConfig { Integrity(Felt), @@ -286,22 +281,46 @@ where } } - let update_state_call = Call { - to: self.piltover_address, - selector: selector!("update_state"), - calldata: { - let calldata = UpdateStateCalldata { program_output }; - let mut raw_calldata = vec![]; - - // Encoding `UpdateStateCalldata` never fails - calldata.encode(&mut raw_calldata).unwrap(); - - raw_calldata - }, + let update_state_call = if let Some(pointer) = new_da.pointer { + let da_layer_info = DaLayerInfo { + height: pointer.height.into(), + commitment: Felt::from_bytes_be(&pointer.commitment), + }; + info!( + block_number = new_da.block_number; + "Submitting DA layer info with height {} and commitment {:#064x}", + da_layer_info.height, + da_layer_info.commitment + ); + Call { + to: self.piltover_address, + selector: selector!("update_state"), + calldata: { + use cainome::cairo_serde::CairoSerde; + let piltover_input = PiltoverInput::LayoutBridgeOutputWithDa(( + program_output, + da_layer_info, + )); + ::cairo_serialize(&piltover_input) + }, + } + } else { + info!( + block_number = new_da.block_number; + "No DA layer info provided, submitting without DA", + ); + Call { + to: self.piltover_address, + selector: selector!("update_state"), + calldata: { + use cainome::cairo_serde::CairoSerde; + let piltover_input = PiltoverInput::LayoutBridgeOutputNoDa(program_output); + ::cairo_serialize(&piltover_input) + }, + } }; let execution = self.account.execute_v3(vec![update_state_call]); - // TODO: error handling let fees = crate::utils::retry_with_backoff( || execution.estimate_fee(), From bc71b38516dbd1f13bdf1e47f2b40f34ca45db44 Mon Sep 17 00:00:00 2001 From: Mateusz Chudkowski Date: Fri, 30 Jan 2026 16:24:46 +0100 Subject: [PATCH 4/5] celestia configurable --- bin/saya/src/any.rs | 87 ++++++++++++++++++++++++++++++++++++++ bin/saya/src/persistent.rs | 40 +++++++++++++----- 2 files changed, 116 insertions(+), 11 deletions(-) diff --git a/bin/saya/src/any.rs b/bin/saya/src/any.rs index 686bc02..df07a00 100644 --- a/bin/saya/src/any.rs +++ b/bin/saya/src/any.rs @@ -1,6 +1,12 @@ use anyhow::Result; use saya_core::{ block_ingestor::BlockInfo, + data_availability::{ + CelestiaDataAvailabilityBackend, CelestiaDataAvailabilityBackendBuilder, + DataAvailabilityBackend, DataAvailabilityBackendBuilder, DataAvailabilityCursor, + DataAvailabilityPayload, DataAvailabilityPointer, NoopDataAvailabilityBackend, + NoopDataAvailabilityBackendBuilder, + }, prover::{ AtlanticLayoutBridgeProver, AtlanticLayoutBridgeProverBuilder, MockLayoutBridgeProver, MockLayoutBridgeProverBuilder, Prover, ProverBuilder, SnosProof, @@ -22,6 +28,87 @@ pub enum AnyLayoutBridgeProverBuilder { Mock(MockLayoutBridgeProverBuilder), } +#[derive(Debug)] +pub enum AnyDataAvailabilityLayer

{ + Celestia(Box>), + Noop(NoopDataAvailabilityBackend

), +} + +#[derive(Debug)] +pub enum AnyDataAvailabilityLayerBuilder

{ + Celestia(Box>), + Noop(NoopDataAvailabilityBackendBuilder

), +} + +impl

DataAvailabilityBackend for AnyDataAvailabilityLayer

+where + P: DataAvailabilityPayload + 'static, +{ + type Payload = P; +} + +impl

Daemon for AnyDataAvailabilityLayer

+where + P: DataAvailabilityPayload + 'static, +{ + fn shutdown_handle(&self) -> ShutdownHandle { + match self { + Self::Celestia(inner) => inner.shutdown_handle(), + Self::Noop(inner) => inner.shutdown_handle(), + } + } + + fn start(self) { + match self { + Self::Celestia(inner) => inner.start(), + Self::Noop(inner) => inner.start(), + } + } +} + +impl

DataAvailabilityBackendBuilder for AnyDataAvailabilityLayerBuilder

+where + P: DataAvailabilityPayload + 'static, +{ + type Backend = AnyDataAvailabilityLayer

; + + fn build(self) -> Result { + Ok(match self { + Self::Celestia(inner) => AnyDataAvailabilityLayer::Celestia(Box::new(inner.build()?)), + Self::Noop(inner) => AnyDataAvailabilityLayer::Noop(inner.build()?), + }) + } + + fn last_pointer(self, last_pointer: Option) -> Self { + match self { + Self::Celestia(inner) => Self::Celestia(Box::new(inner.last_pointer(last_pointer))), + Self::Noop(inner) => Self::Noop(inner.last_pointer(last_pointer)), + } + } + + fn proof_channel( + self, + proof_channel: Receiver<::Payload>, + ) -> Self { + match self { + Self::Celestia(inner) => Self::Celestia(Box::new(inner.proof_channel(proof_channel))), + Self::Noop(inner) => Self::Noop(inner.proof_channel(proof_channel)), + } + } + + fn cursor_channel( + self, + cursor_channel: Sender< + DataAvailabilityCursor<::Payload>, + >, + ) -> Self { + match self { + Self::Celestia(inner) => Self::Celestia(Box::new(inner.cursor_channel(cursor_channel))), + Self::Noop(inner) => Self::Noop(inner.cursor_channel(cursor_channel)), + } + } +} + impl Prover for AnyLayoutBridgeProver where DB: PersistantStorage + Send + Sync + Clone + 'static, diff --git a/bin/saya/src/persistent.rs b/bin/saya/src/persistent.rs index bdc0000..95e9b65 100644 --- a/bin/saya/src/persistent.rs +++ b/bin/saya/src/persistent.rs @@ -4,7 +4,9 @@ use anyhow::Result; use clap::{Parser, Subcommand}; use saya_core::{ block_ingestor::PollingBlockIngestorBuilder, - data_availability::CelestiaDataAvailabilityBackendBuilder, + data_availability::{ + CelestiaDataAvailabilityBackendBuilder, NoopDataAvailabilityBackendBuilder, + }, orchestrator::PersistentOrchestratorBuilder, prover::{ AtlanticLayoutBridgeProverBuilder, AtlanticSnosProverBuilder, @@ -23,7 +25,7 @@ use starknet_types_core::felt::Felt; use url::Url; use crate::{ - any::AnyLayoutBridgeProverBuilder, + any::{AnyDataAvailabilityLayerBuilder, AnyLayoutBridgeProverBuilder}, common::{calculate_workers_per_stage, NUMBER_OF_STAGES, SAYA_DB_PATH}, sovereign::validate_non_empty, }; @@ -83,12 +85,19 @@ struct Start { /// Configuration for OS pie generation #[clap(flatten)] hints: HintsConfiguration, + /// Celestia configuration + #[clap(flatten)] + celestia: CelestiaConfiguration, +} + +#[derive(Debug, Parser, Clone)] +struct CelestiaConfiguration { /// Celestia RPC endpoint URL #[clap(long, env)] - celestia_rpc: Url, + celestia_rpc: Option, /// Celestia RPC node auth token #[clap(long, env)] - celestia_token: String, + celestia_token: Option, /// Celestia key name #[clap(long, env)] celestia_key_name: Option, @@ -200,13 +209,22 @@ impl Start { ), layout_bridge_prover_builder, ); - let da_builder = CelestiaDataAvailabilityBackendBuilder::new( - self.celestia_rpc, - self.celestia_token, - self.celestia_namespace, - self.celestia_key_name, - ) - .unwrap(); + + let da_builder = if let (Some(celestia_rpc), Some(celestia_token)) = + (self.celestia.celestia_rpc, self.celestia.celestia_token) + { + AnyDataAvailabilityLayerBuilder::Celestia(Box::new( + CelestiaDataAvailabilityBackendBuilder::new( + celestia_rpc, + celestia_token, + self.celestia.celestia_namespace, + self.celestia.celestia_key_name, + ) + .unwrap(), + )) + } else { + AnyDataAvailabilityLayerBuilder::Noop(NoopDataAvailabilityBackendBuilder::new()) + }; let settlement_builder = PiltoverSettlementBackendBuilder::new( self.settlement_rpc, From b9bcc50b1cbfae6ca99cb598f0fdb322bc2e7a7b Mon Sep 17 00:00:00 2001 From: Mateusz Chudkowski Date: Wed, 4 Feb 2026 10:43:04 +0100 Subject: [PATCH 5/5] post-reviev fixes --- Cargo.lock | 2 +- Cargo.toml | 2 +- saya/core/src/block_ingestor/mod.rs | 7 - saya/core/src/block_ingestor/polling.rs | 3 +- saya/core/src/data_availability/celestia.rs | 8 +- saya/core/src/data_availability/mod.rs | 2 +- .../core/src/prover/atlantic/layout_bridge.rs | 5 +- saya/core/src/prover/mod.rs | 6 +- saya/core/src/storage/sql_lite/mod.rs | 12 +- saya/core/src/storage/sql_lite/storage.rs | 147 +++++++++++++++++- 10 files changed, 164 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4ee15a..055958e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5126,7 +5126,7 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "piltover" version = "0.1.0" -source = "git+https://github.com/cartridge-gg/piltover.git?branch=feat%2Fupdate-starknet-output#3edc066544587512141127c19f641ac6a8cd941a" +source = "git+https://github.com/cartridge-gg/piltover.git?rev=ab34aaa#ab34aaaf7be0847fadada4c37efdc1c8f484667c" dependencies = [ "cainome", "starknet", diff --git a/Cargo.toml b/Cargo.toml index 4cf3b7a..43b224e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,5 +54,5 @@ tokio-util = { version = "0.7.13", default-features = false } url = { version = "2.5.4", default-features = false } zip = { version = "2.2.2", default-features = false, features = ["deflate"] } sqlx = { version = "0.8.2", features = [ "chrono", "macros", "regexp", "runtime-async-std", "runtime-tokio", "sqlite", "uuid" ] } -piltover = {package = "piltover", git = "https://github.com/cartridge-gg/piltover.git", branch = "feat/update-starknet-output" } +piltover = {package = "piltover", git = "https://github.com/cartridge-gg/piltover.git", rev = "ab34aaa" } cainome = { version = "0.10.1", features = ["abigen-rs"] } diff --git a/saya/core/src/block_ingestor/mod.rs b/saya/core/src/block_ingestor/mod.rs index f3558b4..121cbd0 100644 --- a/saya/core/src/block_ingestor/mod.rs +++ b/saya/core/src/block_ingestor/mod.rs @@ -27,10 +27,3 @@ pub struct BlockInfo { pub status: BlockStatus, pub state_update: Option, } - -#[derive(Debug, Clone)] -pub struct BlobPointer { - pub height: u64, - pub commitment: [u8; 32], - pub namespace: String, -} diff --git a/saya/core/src/block_ingestor/polling.rs b/saya/core/src/block_ingestor/polling.rs index 2b8c5b0..6e75b46 100644 --- a/saya/core/src/block_ingestor/polling.rs +++ b/saya/core/src/block_ingestor/polling.rs @@ -117,6 +117,7 @@ where starknet::core::types::MaybePreConfirmedStateUpdate::Update(state_update) => { state_update } + //TODO: handle this case properly starknet::core::types::MaybePreConfirmedStateUpdate::PreConfirmedUpdate(_) => { panic!("PreConfirmedStateUpdate not supported") } @@ -179,7 +180,7 @@ where let new_block = BlockInfo { number: block_number, status: BlockStatus::SnosPieGenerated, - state_update: None, + state_update: Some(state_update.clone()), }; let pie_bytes = compress_pie(pie.clone()).await.unwrap(); diff --git a/saya/core/src/data_availability/celestia.rs b/saya/core/src/data_availability/celestia.rs index f02fed7..87b5d56 100644 --- a/saya/core/src/data_availability/celestia.rs +++ b/saya/core/src/data_availability/celestia.rs @@ -68,13 +68,7 @@ where ciborium::into_writer(&packet, &mut serialized_packet).unwrap(); // TODO: error handling - let blob = Blob::new( - self.namespace, - serialized_packet, - None, - AppVersion::latest(), - ) - .unwrap(); + let blob = Blob::new(self.namespace, serialized_packet, None, AppVersion::V7).unwrap(); let commitment = blob.clone().commitment; let commitment = commitment.hash(); diff --git a/saya/core/src/data_availability/mod.rs b/saya/core/src/data_availability/mod.rs index 7f61ae6..d9b59ef 100644 --- a/saya/core/src/data_availability/mod.rs +++ b/saya/core/src/data_availability/mod.rs @@ -76,7 +76,7 @@ pub struct SovereignPacket { /// posting mechanism in place for now. #[derive(Debug, Serialize, Deserialize)] pub struct PersistentPacket { - pub state_update: StateUpdate, + pub state_update: Option, } // TODO: abstract over this to allow other DA backends. diff --git a/saya/core/src/prover/atlantic/layout_bridge.rs b/saya/core/src/prover/atlantic/layout_bridge.rs index c582ac4..1714929 100644 --- a/saya/core/src/prover/atlantic/layout_bridge.rs +++ b/saya/core/src/prover/atlantic/layout_bridge.rs @@ -67,7 +67,10 @@ where }; let block_number_u32 = new_snos_proof.block_number.try_into().unwrap(); - let state_update = db.get_state_update(block_number_u32).await.unwrap(); + let state_update = db + .get_state_update(block_number_u32) + .await + .map_err(|e| ProverError::MetadataFetch(e.to_string()))?; match db .get_proof(block_number_u32, crate::storage::Step::Bridge) .await diff --git a/saya/core/src/prover/mod.rs b/saya/core/src/prover/mod.rs index bbee4b1..5f73328 100644 --- a/saya/core/src/prover/mod.rs +++ b/saya/core/src/prover/mod.rs @@ -81,10 +81,8 @@ impl DataAvailabilityPayload for BlockInfo { } fn into_packet(self, _ctx: DataAvailabilityPacketContext) -> Self::Packet { - if let Some(state_update) = self.state_update { - PersistentPacket { state_update } - } else { - panic!("BlockInfo must contain state_update to be converted into PersistentPacket"); + PersistentPacket { + state_update: self.state_update, } } } diff --git a/saya/core/src/storage/sql_lite/mod.rs b/saya/core/src/storage/sql_lite/mod.rs index ca5bd19..d6a2a93 100644 --- a/saya/core/src/storage/sql_lite/mod.rs +++ b/saya/core/src/storage/sql_lite/mod.rs @@ -89,7 +89,7 @@ impl SqliteDb { r#" CREATE TABLE IF NOT EXISTS pies ( id INTEGER PRIMARY KEY AUTOINCREMENT, - block_id INTEGER NOT NULL REFERENCES blocks(block_id) ON DELETE CASCADE, + block_id INTEGER NOT NULL UNIQUE REFERENCES blocks(block_id) ON DELETE CASCADE, snos_pie BLOB, bridge_pie BLOB ); @@ -104,7 +104,7 @@ impl SqliteDb { query( r#"CREATE TABLE IF NOT EXISTS proofs ( id INTEGER PRIMARY KEY AUTOINCREMENT, - block_id INTEGER NOT NULL REFERENCES blocks(block_id) ON DELETE CASCADE, + block_id INTEGER NOT NULL UNIQUE REFERENCES blocks(block_id) ON DELETE CASCADE, snos_proof BLOB, bridge_proof BLOB );"#, @@ -118,7 +118,7 @@ impl SqliteDb { query( r#"CREATE TABLE IF NOT EXISTS job_ids ( id INTEGER PRIMARY KEY AUTOINCREMENT, - block_id INTEGER NOT NULL REFERENCES blocks(block_id) ON DELETE CASCADE, + block_id INTEGER NOT NULL UNIQUE REFERENCES blocks(block_id) ON DELETE CASCADE, snos_proof_query_id TEXT, trace_gen_query_id TEXT, bridge_proof_query_id TEXT @@ -149,9 +149,9 @@ impl SqliteDb { query( r#" CREATE TABLE IF NOT EXISTS state_updates ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - block_id INTEGER NOT NULL, - state_update BLOB NOT NULL + id INTEGER PRIMARY KEY AUTOINCREMENT, + block_id INTEGER NOT NULL UNIQUE REFERENCES blocks(block_id) ON DELETE CASCADE, + state_update BLOB NOT NULL ); "#, ) diff --git a/saya/core/src/storage/sql_lite/storage.rs b/saya/core/src/storage/sql_lite/storage.rs index a20029f..b48fab6 100644 --- a/saya/core/src/storage/sql_lite/storage.rs +++ b/saya/core/src/storage/sql_lite/storage.rs @@ -313,7 +313,7 @@ impl PersistantStorage for SqliteDb { ) -> anyhow::Result<()> { let serialized = serde_json::to_vec(&state_update)?; let mut tx = self.pool.begin().await?; - query("INSERT OR IGNORE INTO state_updates (block_id, state_update) VALUES (?, ?);") + query("INSERT OR REPLACE INTO state_updates (block_id, state_update) VALUES (?, ?);") .bind(block_number) .bind(serialized) .execute(&mut *tx) @@ -338,6 +338,9 @@ impl PersistantStorage for SqliteDb { #[cfg(test)] mod tests { + use integrity::Felt; + use starknet::core::types::StateDiff; + use crate::storage::sql_lite::IN_MEMORY_DB; use super::*; @@ -558,4 +561,146 @@ mod tests { assert_eq!(failed_blocks, vec![(1, "failed".to_string())]); } + + #[tokio::test] + async fn test_add_state_update_and_get_state_update() { + let db = SqliteDb::new(IN_MEMORY_DB).await.unwrap(); + + db.initialize_block(1).await.unwrap(); + + let state_update = starknet::core::types::StateUpdate { + block_hash: Felt::ZERO, + new_root: Felt::ZERO, + old_root: Felt::ZERO, + state_diff: StateDiff { + storage_diffs: vec![], + declared_classes: vec![], + deployed_contracts: vec![], + nonces: vec![], + deprecated_declared_classes: vec![], + replaced_classes: vec![], + }, + }; + + db.add_state_update(1, state_update.clone()).await.unwrap(); + let result = db.get_state_update(1).await.unwrap(); + + assert_eq!(result.block_hash, state_update.block_hash); + assert_eq!(result.new_root, state_update.new_root); + assert_eq!(result.old_root, state_update.old_root); + } + + #[tokio::test] + async fn test_unique_constraint_enforced_on_pies() { + let db = SqliteDb::new(IN_MEMORY_DB).await.unwrap(); + + db.initialize_block(1).await.unwrap(); + + let pie1 = vec![1, 2, 3]; + let pie2 = vec![4, 5, 6]; + + // Add first pie + db.add_pie(1, pie1.clone(), Step::Snos).await.unwrap(); + let result1 = db.get_pie(1, Step::Snos).await.unwrap(); + assert_eq!(result1, pie1); + + // Update with second pie (should update, not create duplicate) + db.add_pie(1, pie2.clone(), Step::Snos).await.unwrap(); + let result2 = db.get_pie(1, Step::Snos).await.unwrap(); + assert_eq!(result2, pie2); + } + + #[tokio::test] + async fn test_unique_constraint_enforced_on_proofs() { + let db = SqliteDb::new(IN_MEMORY_DB).await.unwrap(); + + db.initialize_block(1).await.unwrap(); + + let proof1 = vec![10, 20, 30]; + let proof2 = vec![40, 50, 60]; + + // Add first proof + db.add_proof(1, proof1.clone(), Step::Snos).await.unwrap(); + let result1 = db.get_proof(1, Step::Snos).await.unwrap(); + assert_eq!(result1, proof1); + + // Update with second proof (should update, not create duplicate) + db.add_proof(1, proof2.clone(), Step::Snos).await.unwrap(); + let result2 = db.get_proof(1, Step::Snos).await.unwrap(); + assert_eq!(result2, proof2); + } + + #[tokio::test] + async fn test_unique_constraint_enforced_on_job_ids() { + let db = SqliteDb::new(IN_MEMORY_DB).await.unwrap(); + + db.initialize_block(1).await.unwrap(); + + let query_id_1 = "query_1".to_string(); + let query_id_2 = "query_2".to_string(); + + // Add first query id + db.add_query_id(1, query_id_1.clone(), Query::SnosProof) + .await + .unwrap(); + let result1 = db.get_query_id(1, Query::SnosProof).await.unwrap(); + assert_eq!(result1, query_id_1); + + // Update with second query id (should update, not create duplicate) + db.add_query_id(1, query_id_2.clone(), Query::SnosProof) + .await + .unwrap(); + let result2 = db.get_query_id(1, Query::SnosProof).await.unwrap(); + assert_eq!(result2, query_id_2); + } + + #[tokio::test] + async fn test_unique_constraint_enforced_on_state_updates() { + let db = SqliteDb::new(IN_MEMORY_DB).await.unwrap(); + + db.initialize_block(1).await.unwrap(); + + let state_update_1 = starknet::core::types::StateUpdate { + block_hash: Felt::ZERO, + new_root: Felt::ZERO, + old_root: Felt::ZERO, + state_diff: StateDiff { + storage_diffs: vec![], + declared_classes: vec![], + deployed_contracts: vec![], + nonces: vec![], + deprecated_declared_classes: vec![], + replaced_classes: vec![], + }, + }; + + let state_update_2 = starknet::core::types::StateUpdate { + block_hash: Felt::ONE, + new_root: Felt::ONE, + old_root: Felt::ONE, + state_diff: StateDiff { + storage_diffs: vec![], + declared_classes: vec![], + deployed_contracts: vec![], + nonces: vec![], + deprecated_declared_classes: vec![], + replaced_classes: vec![], + }, + }; + + // Add first state update + db.add_state_update(1, state_update_1.clone()) + .await + .unwrap(); + let result1 = db.get_state_update(1).await.unwrap(); + assert_eq!(result1.block_hash, state_update_1.block_hash); + + // Update with second state update (should update, not create duplicate) + db.add_state_update(1, state_update_2.clone()) + .await + .unwrap(); + let result2 = db.get_state_update(1).await.unwrap(); + assert_eq!(result2.new_root, state_update_2.new_root); + assert_eq!(result2.old_root, state_update_2.old_root); + } }