From a12f24b6e988fa96abf0c99eb1b94ab0528579be Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Tue, 1 Jul 2025 15:09:46 +0200 Subject: [PATCH 01/16] feat: add rollkit rust types lib crate --- .gitignore | 1 + Cargo.lock | 1195 ++++++++++++ Cargo.toml | 17 + crates/rollkit-types/Cargo.toml | 14 + crates/rollkit-types/build.rs | 25 + crates/rollkit-types/src/lib.rs | 1 + crates/rollkit-types/src/proto/mod.rs | 5 + crates/rollkit-types/src/proto/rollkit.v1.rs | 1820 ++++++++++++++++++ 8 files changed, 3078 insertions(+) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 crates/rollkit-types/Cargo.toml create mode 100644 crates/rollkit-types/build.rs create mode 100644 crates/rollkit-types/src/lib.rs create mode 100644 crates/rollkit-types/src/proto/mod.rs create mode 100644 crates/rollkit-types/src/proto/rollkit.v1.rs diff --git a/.gitignore b/.gitignore index 7426d092b7..f2bb112446 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ build .DS_Store coverage.out execution/evm/jwttoken +target \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..2394d58994 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1195 @@ +# This file is automatically @generated by Cargo. +# 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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[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", +] + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[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 = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.10.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.10.0", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rollkit-types" +version = "0.1.0" +dependencies = [ + "prost", + "prost-build", + "prost-types", + "tonic", + "tonic-build", + "walkdir", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio" +version = "1.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "quote", + "syn", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..47925408ff --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[workspace.package] +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +repository = "https://github.com/rollkit/rollkit" + +[workspace] +members = ["crates/rollkit-types"] +resolver = "3" + +[workspace.dependencies] +prost = "0.12" +prost-build = "0.12" +prost-types = "0.12" +tonic = { version = "0.10", features = ["transport"] } +tonic-build = "0.10" +walkdir = "2.5.0" diff --git a/crates/rollkit-types/Cargo.toml b/crates/rollkit-types/Cargo.toml new file mode 100644 index 0000000000..f131f16952 --- /dev/null +++ b/crates/rollkit-types/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rollkit-types" +version = "0.1.0" +edition = "2021" + +[build-dependencies] +tonic-build = { workspace = true } +prost-build = { workspace = true } +walkdir = { workspace = true } + +[dependencies] +prost = { workspace = true } +prost-types = { workspace = true } +tonic = { workspace = true, features = ["transport"] } diff --git a/crates/rollkit-types/build.rs b/crates/rollkit-types/build.rs new file mode 100644 index 0000000000..25cf8aa50a --- /dev/null +++ b/crates/rollkit-types/build.rs @@ -0,0 +1,25 @@ +use std::path::PathBuf; +use walkdir::WalkDir; + +// Collect all .proto files recursively under /proto/ and compile. +fn main() -> Result<(), Box> { + let proto_files: Vec = WalkDir::new("../../proto") + .into_iter() + .filter_map(|entry| { + let path = entry.ok()?.path().to_path_buf(); + if path.extension().map_or(false, |ext| ext == "proto") { + Some(path) + } else { + None + } + }) + .collect(); + + tonic_build::configure() + .build_server(true) + .build_client(true) + .out_dir("src/proto") + .compile(&proto_files, &["../../proto"])?; + + Ok(()) +} diff --git a/crates/rollkit-types/src/lib.rs b/crates/rollkit-types/src/lib.rs new file mode 100644 index 0000000000..febacec69e --- /dev/null +++ b/crates/rollkit-types/src/lib.rs @@ -0,0 +1 @@ +pub mod proto; diff --git a/crates/rollkit-types/src/proto/mod.rs b/crates/rollkit-types/src/proto/mod.rs new file mode 100644 index 0000000000..96b8f4be97 --- /dev/null +++ b/crates/rollkit-types/src/proto/mod.rs @@ -0,0 +1,5 @@ +pub mod rollkit { + pub mod v1 { + include!("rollkit.v1.rs"); + } +} diff --git a/crates/rollkit-types/src/proto/rollkit.v1.rs b/crates/rollkit-types/src/proto/rollkit.v1.rs new file mode 100644 index 0000000000..c66970c5e4 --- /dev/null +++ b/crates/rollkit-types/src/proto/rollkit.v1.rs @@ -0,0 +1,1820 @@ +// This file is @generated by prost-build. +/// The SignRequest holds the bytes we want to sign. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SignRequest { + #[prost(bytes = "vec", tag = "1")] + pub message: ::prost::alloc::vec::Vec, +} +/// The SignResponse returns the signature bytes. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SignResponse { + #[prost(bytes = "vec", tag = "1")] + pub signature: ::prost::alloc::vec::Vec, +} +/// The GetPublicRequest is an empty request. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetPublicRequest {} +/// The GetPublicResponse returns the public key. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetPublicResponse { + #[prost(bytes = "vec", tag = "1")] + pub public_key: ::prost::alloc::vec::Vec, +} +/// Generated client implementations. +pub mod signer_service_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// The SignerService defines the RPCs to sign and to retrieve the public key. + #[derive(Debug, Clone)] + pub struct SignerServiceClient { + inner: tonic::client::Grpc, + } + impl SignerServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl SignerServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> SignerServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + SignerServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Sign signs the given message. + pub async fn sign( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rollkit.v1.SignerService/Sign", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("rollkit.v1.SignerService", "Sign")); + self.inner.unary(req, path, codec).await + } + /// GetPublic returns the public key. + pub async fn get_public( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rollkit.v1.SignerService/GetPublic", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("rollkit.v1.SignerService", "GetPublic")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod signer_service_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with SignerServiceServer. + #[async_trait] + pub trait SignerService: Send + Sync + 'static { + /// Sign signs the given message. + async fn sign( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// GetPublic returns the public key. + async fn get_public( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + /// The SignerService defines the RPCs to sign and to retrieve the public key. + #[derive(Debug)] + pub struct SignerServiceServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl SignerServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for SignerServiceServer + where + T: SignerService, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/rollkit.v1.SignerService/Sign" => { + #[allow(non_camel_case_types)] + struct SignSvc(pub Arc); + impl< + T: SignerService, + > tonic::server::UnaryService for SignSvc { + type Response = super::SignResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::sign(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = SignSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/rollkit.v1.SignerService/GetPublic" => { + #[allow(non_camel_case_types)] + struct GetPublicSvc(pub Arc); + impl< + T: SignerService, + > tonic::server::UnaryService + for GetPublicSvc { + type Response = super::GetPublicResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_public(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetPublicSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for SignerServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for SignerServiceServer { + const NAME: &'static str = "rollkit.v1.SignerService"; + } +} +/// Version captures the consensus rules for processing a block in the blockchain, +/// including all blockchain data structures and the rules of the application's +/// state transition machine. +/// This is equivalent to the tmversion.Consensus type in Tendermint. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Version { + #[prost(uint64, tag = "1")] + pub block: u64, + #[prost(uint64, tag = "2")] + pub app: u64, +} +/// Header is the header of a block in the blockchain. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Header { + /// Block and App version + #[prost(message, optional, tag = "1")] + pub version: ::core::option::Option, + /// Block height + #[prost(uint64, tag = "2")] + pub height: u64, + /// Block creation time + #[prost(uint64, tag = "3")] + pub time: u64, + /// Previous block info + #[prost(bytes = "vec", tag = "4")] + pub last_header_hash: ::prost::alloc::vec::Vec, + /// Commit from aggregator(s) from the last block + #[prost(bytes = "vec", tag = "5")] + pub last_commit_hash: ::prost::alloc::vec::Vec, + /// Block.Data root aka Transactions + #[prost(bytes = "vec", tag = "6")] + pub data_hash: ::prost::alloc::vec::Vec, + /// Consensus params for current block + #[prost(bytes = "vec", tag = "7")] + pub consensus_hash: ::prost::alloc::vec::Vec, + /// State after applying txs from the current block + #[prost(bytes = "vec", tag = "8")] + pub app_hash: ::prost::alloc::vec::Vec, + /// Root hash of all results from the txs from the previous block. + /// This is ABCI specific but smart-contract chains require some way of committing + /// to transaction receipts/results. + #[prost(bytes = "vec", tag = "9")] + pub last_results_hash: ::prost::alloc::vec::Vec, + /// Original proposer of the block + /// Note that the address can be derived from the pubkey which can be derived + /// from the signature when using secp256k. + /// We keep this in case users choose another signature format where the + /// pubkey can't be recovered by the signature (e.g. ed25519). + #[prost(bytes = "vec", tag = "10")] + pub proposer_address: ::prost::alloc::vec::Vec, + /// validatorhash for compatibility with tendermint light client. + #[prost(bytes = "vec", tag = "11")] + pub validator_hash: ::prost::alloc::vec::Vec, + /// Chain ID the block belongs to + #[prost(string, tag = "12")] + pub chain_id: ::prost::alloc::string::String, +} +/// SignedHeader is a header with a signature and a signer. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SignedHeader { + #[prost(message, optional, tag = "1")] + pub header: ::core::option::Option
, + #[prost(bytes = "vec", tag = "2")] + pub signature: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "3")] + pub signer: ::core::option::Option, +} +/// Signer is a signer of a block in the blockchain. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Signer { + /// Address of the signer + #[prost(bytes = "vec", tag = "1")] + pub address: ::prost::alloc::vec::Vec, + /// Public key of the signer + #[prost(bytes = "vec", tag = "2")] + pub pub_key: ::prost::alloc::vec::Vec, +} +/// Metadata is the metadata of a block in the blockchain. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Metadata { + /// chain id + #[prost(string, tag = "1")] + pub chain_id: ::prost::alloc::string::String, + /// Block height + #[prost(uint64, tag = "2")] + pub height: u64, + /// Block creation time + #[prost(uint64, tag = "3")] + pub time: u64, + /// Previous block info + #[prost(bytes = "vec", tag = "4")] + pub last_data_hash: ::prost::alloc::vec::Vec, +} +/// Data is the data of a block in the blockchain. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Data { + #[prost(message, optional, tag = "1")] + pub metadata: ::core::option::Option, + #[prost(bytes = "vec", repeated, tag = "2")] + pub txs: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, +} +/// SignedData is a data with a signature and a signer. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SignedData { + #[prost(message, optional, tag = "1")] + pub data: ::core::option::Option, + #[prost(bytes = "vec", tag = "2")] + pub signature: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "3")] + pub signer: ::core::option::Option, +} +/// Vote is a vote for a block in the blockchain. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Vote { + /// Chain ID + #[prost(string, tag = "1")] + pub chain_id: ::prost::alloc::string::String, + /// Block height + #[prost(uint64, tag = "2")] + pub height: u64, + /// Timestamp + #[prost(message, optional, tag = "3")] + pub timestamp: ::core::option::Option<::prost_types::Timestamp>, + /// Block ID hash + #[prost(bytes = "vec", tag = "4")] + pub block_id_hash: ::prost::alloc::vec::Vec, + /// Validator address + #[prost(bytes = "vec", tag = "5")] + pub validator_address: ::prost::alloc::vec::Vec, +} +/// State is the state of the blockchain. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct State { + #[prost(message, optional, tag = "1")] + pub version: ::core::option::Option, + #[prost(string, tag = "2")] + pub chain_id: ::prost::alloc::string::String, + #[prost(uint64, tag = "3")] + pub initial_height: u64, + #[prost(uint64, tag = "4")] + pub last_block_height: u64, + #[prost(message, optional, tag = "5")] + pub last_block_time: ::core::option::Option<::prost_types::Timestamp>, + #[prost(uint64, tag = "6")] + pub da_height: u64, + #[prost(bytes = "vec", tag = "7")] + pub last_results_hash: ::prost::alloc::vec::Vec, + #[prost(bytes = "vec", tag = "8")] + pub app_hash: ::prost::alloc::vec::Vec, +} +/// GetPeerInfoResponse defines the response for retrieving peer information +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetPeerInfoResponse { + /// List of connected peers + #[prost(message, repeated, tag = "1")] + pub peers: ::prost::alloc::vec::Vec, +} +/// GetNetInfoResponse defines the response for retrieving network information +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetNetInfoResponse { + /// Network information + #[prost(message, optional, tag = "1")] + pub net_info: ::core::option::Option, +} +/// PeerInfo contains information about a connected peer +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PeerInfo { + /// Peer ID + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// Peer address + #[prost(string, tag = "2")] + pub address: ::prost::alloc::string::String, +} +/// NetInfo contains information about the network +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NetInfo { + /// Network ID + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// Listen address + #[prost(string, repeated, tag = "2")] + pub listen_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// List of connected peers + #[prost(string, repeated, tag = "3")] + pub connected_peers: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// Generated client implementations. +pub mod p2p_service_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// P2PService defines the RPC service for the P2P package + #[derive(Debug, Clone)] + pub struct P2pServiceClient { + inner: tonic::client::Grpc, + } + impl P2pServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl P2pServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> P2pServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + P2pServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// GetPeerInfo returns information about the connected peers + pub async fn get_peer_info( + &mut self, + request: impl tonic::IntoRequest<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rollkit.v1.P2PService/GetPeerInfo", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("rollkit.v1.P2PService", "GetPeerInfo")); + self.inner.unary(req, path, codec).await + } + /// GetNetInfo returns network information + pub async fn get_net_info( + &mut self, + request: impl tonic::IntoRequest<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rollkit.v1.P2PService/GetNetInfo", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("rollkit.v1.P2PService", "GetNetInfo")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod p2p_service_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with P2pServiceServer. + #[async_trait] + pub trait P2pService: Send + Sync + 'static { + /// GetPeerInfo returns information about the connected peers + async fn get_peer_info( + &self, + request: tonic::Request<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// GetNetInfo returns network information + async fn get_net_info( + &self, + request: tonic::Request<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + /// P2PService defines the RPC service for the P2P package + #[derive(Debug)] + pub struct P2pServiceServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl P2pServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for P2pServiceServer + where + T: P2pService, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/rollkit.v1.P2PService/GetPeerInfo" => { + #[allow(non_camel_case_types)] + struct GetPeerInfoSvc(pub Arc); + impl tonic::server::UnaryService<()> + for GetPeerInfoSvc { + type Response = super::GetPeerInfoResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call(&mut self, request: tonic::Request<()>) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_peer_info(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetPeerInfoSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/rollkit.v1.P2PService/GetNetInfo" => { + #[allow(non_camel_case_types)] + struct GetNetInfoSvc(pub Arc); + impl tonic::server::UnaryService<()> + for GetNetInfoSvc { + type Response = super::GetNetInfoResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call(&mut self, request: tonic::Request<()>) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_net_info(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetNetInfoSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for P2pServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for P2pServiceServer { + const NAME: &'static str = "rollkit.v1.P2PService"; + } +} +/// Batch is a collection of transactions. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Batch { + #[prost(bytes = "vec", repeated, tag = "1")] + pub txs: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, +} +/// GetHealthResponse defines the response for retrieving health status +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetHealthResponse { + /// Health status + #[prost(enumeration = "HealthStatus", tag = "1")] + pub status: i32, +} +/// HealthStatus defines the health status of the node +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum HealthStatus { + /// Unknown health status + Unknown = 0, + /// Healthy status (Healthy) + Pass = 1, + /// Degraded but still serving + Warn = 2, + /// Hard fail + Fail = 3, +} +impl HealthStatus { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + HealthStatus::Unknown => "UNKNOWN", + HealthStatus::Pass => "PASS", + HealthStatus::Warn => "WARN", + HealthStatus::Fail => "FAIL", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "UNKNOWN" => Some(Self::Unknown), + "PASS" => Some(Self::Pass), + "WARN" => Some(Self::Warn), + "FAIL" => Some(Self::Fail), + _ => None, + } + } +} +/// Generated client implementations. +pub mod health_service_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// HealthService defines the RPC service for the health package + #[derive(Debug, Clone)] + pub struct HealthServiceClient { + inner: tonic::client::Grpc, + } + impl HealthServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl HealthServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> HealthServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + HealthServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Livez returns the health status of the node + pub async fn livez( + &mut self, + request: impl tonic::IntoRequest<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rollkit.v1.HealthService/Livez", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("rollkit.v1.HealthService", "Livez")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod health_service_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with HealthServiceServer. + #[async_trait] + pub trait HealthService: Send + Sync + 'static { + /// Livez returns the health status of the node + async fn livez( + &self, + request: tonic::Request<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + /// HealthService defines the RPC service for the health package + #[derive(Debug)] + pub struct HealthServiceServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl HealthServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for HealthServiceServer + where + T: HealthService, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/rollkit.v1.HealthService/Livez" => { + #[allow(non_camel_case_types)] + struct LivezSvc(pub Arc); + impl tonic::server::UnaryService<()> + for LivezSvc { + type Response = super::GetHealthResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call(&mut self, request: tonic::Request<()>) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::livez(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = LivezSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for HealthServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for HealthServiceServer { + const NAME: &'static str = "rollkit.v1.HealthService"; + } +} +/// Block contains all the components of a complete block +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Block { + #[prost(message, optional, tag = "1")] + pub header: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub data: ::core::option::Option, +} +/// GetBlockRequest defines the request for retrieving a block +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetBlockRequest { + /// The height or hash of the block to retrieve + #[prost(oneof = "get_block_request::Identifier", tags = "1, 2")] + pub identifier: ::core::option::Option, +} +/// Nested message and enum types in `GetBlockRequest`. +pub mod get_block_request { + /// The height or hash of the block to retrieve + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Identifier { + #[prost(uint64, tag = "1")] + Height(u64), + #[prost(bytes, tag = "2")] + Hash(::prost::alloc::vec::Vec), + } +} +/// GetBlockResponse defines the response for retrieving a block +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetBlockResponse { + #[prost(message, optional, tag = "1")] + pub block: ::core::option::Option, + #[prost(uint64, tag = "2")] + pub header_da_height: u64, + #[prost(uint64, tag = "3")] + pub data_da_height: u64, +} +/// GetStateResponse defines the response for retrieving the current state +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetStateResponse { + #[prost(message, optional, tag = "1")] + pub state: ::core::option::Option, +} +/// GetMetadataRequest defines the request for retrieving metadata by key +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetMetadataRequest { + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, +} +/// GetMetadataResponse defines the response for retrieving metadata +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetMetadataResponse { + #[prost(bytes = "vec", tag = "1")] + pub value: ::prost::alloc::vec::Vec, +} +/// Generated client implementations. +pub mod store_service_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// StoreService defines the RPC service for the store package + #[derive(Debug, Clone)] + pub struct StoreServiceClient { + inner: tonic::client::Grpc, + } + impl StoreServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl StoreServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> StoreServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + StoreServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// GetBlock returns a block by height or hash + pub async fn get_block( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rollkit.v1.StoreService/GetBlock", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("rollkit.v1.StoreService", "GetBlock")); + self.inner.unary(req, path, codec).await + } + /// GetState returns the current state + pub async fn get_state( + &mut self, + request: impl tonic::IntoRequest<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rollkit.v1.StoreService/GetState", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("rollkit.v1.StoreService", "GetState")); + self.inner.unary(req, path, codec).await + } + /// GetMetadata returns metadata for a specific key + pub async fn get_metadata( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rollkit.v1.StoreService/GetMetadata", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("rollkit.v1.StoreService", "GetMetadata")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod store_service_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with StoreServiceServer. + #[async_trait] + pub trait StoreService: Send + Sync + 'static { + /// GetBlock returns a block by height or hash + async fn get_block( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// GetState returns the current state + async fn get_state( + &self, + request: tonic::Request<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// GetMetadata returns metadata for a specific key + async fn get_metadata( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + /// StoreService defines the RPC service for the store package + #[derive(Debug)] + pub struct StoreServiceServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl StoreServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for StoreServiceServer + where + T: StoreService, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/rollkit.v1.StoreService/GetBlock" => { + #[allow(non_camel_case_types)] + struct GetBlockSvc(pub Arc); + impl< + T: StoreService, + > tonic::server::UnaryService + for GetBlockSvc { + type Response = super::GetBlockResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_block(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetBlockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/rollkit.v1.StoreService/GetState" => { + #[allow(non_camel_case_types)] + struct GetStateSvc(pub Arc); + impl tonic::server::UnaryService<()> + for GetStateSvc { + type Response = super::GetStateResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call(&mut self, request: tonic::Request<()>) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_state(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetStateSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/rollkit.v1.StoreService/GetMetadata" => { + #[allow(non_camel_case_types)] + struct GetMetadataSvc(pub Arc); + impl< + T: StoreService, + > tonic::server::UnaryService + for GetMetadataSvc { + type Response = super::GetMetadataResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_metadata(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetMetadataSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for StoreServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for StoreServiceServer { + const NAME: &'static str = "rollkit.v1.StoreService"; + } +} From 2b053e810c24ae835323c7080ba21aaf49a6a05a Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Tue, 1 Jul 2025 15:19:59 +0200 Subject: [PATCH 02/16] refactor: mv module structure --- crates/rollkit-types/src/lib.rs | 4 +++- crates/rollkit-types/src/proto/mod.rs | 5 ----- 2 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 crates/rollkit-types/src/proto/mod.rs diff --git a/crates/rollkit-types/src/lib.rs b/crates/rollkit-types/src/lib.rs index febacec69e..776941e630 100644 --- a/crates/rollkit-types/src/lib.rs +++ b/crates/rollkit-types/src/lib.rs @@ -1 +1,3 @@ -pub mod proto; +pub mod v1 { + include!("proto/rollkit.v1.rs"); +} diff --git a/crates/rollkit-types/src/proto/mod.rs b/crates/rollkit-types/src/proto/mod.rs deleted file mode 100644 index 96b8f4be97..0000000000 --- a/crates/rollkit-types/src/proto/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod rollkit { - pub mod v1 { - include!("rollkit.v1.rs"); - } -} From 5a0fc4aaca8163c7ed9034e82300e22d1155fe5e Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Wed, 2 Jul 2025 10:36:34 +0200 Subject: [PATCH 03/16] chore: use resolver version 2 to align with 2021 edition --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 47925408ff..2527a7c1fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/rollkit/rollkit" [workspace] members = ["crates/rollkit-types"] -resolver = "3" +resolver = "2" [workspace.dependencies] prost = "0.12" From 7a60b713f8e75846689a74e6c7f32af9dd4fed45 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 2 Jul 2025 15:19:00 +0200 Subject: [PATCH 04/16] add rust types and client for interactions --- Cargo.lock | 386 ++++++++++++++++++ Cargo.toml | 2 +- client/README.md | 42 ++ client/crates/rollkit-client/Cargo.toml | 22 + client/crates/rollkit-client/README.md | 101 +++++ .../crates/rollkit-client/examples/basic.rs | 109 +++++ client/crates/rollkit-client/src/client.rs | 64 +++ client/crates/rollkit-client/src/error.rs | 21 + client/crates/rollkit-client/src/health.rs | 40 ++ client/crates/rollkit-client/src/lib.rs | 40 ++ client/crates/rollkit-client/src/p2p.rs | 56 +++ client/crates/rollkit-client/src/signer.rs | 50 +++ client/crates/rollkit-client/src/store.rs | 93 +++++ .../rollkit-client/tests/integration_test.rs | 35 ++ .../crates}/rollkit-types/Cargo.toml | 0 .../crates}/rollkit-types/build.rs | 4 +- .../crates}/rollkit-types/src/lib.rs | 0 .../rollkit-types/src/proto/rollkit.v1.rs | 0 18 files changed, 1062 insertions(+), 3 deletions(-) create mode 100644 client/README.md create mode 100644 client/crates/rollkit-client/Cargo.toml create mode 100644 client/crates/rollkit-client/README.md create mode 100644 client/crates/rollkit-client/examples/basic.rs create mode 100644 client/crates/rollkit-client/src/client.rs create mode 100644 client/crates/rollkit-client/src/error.rs create mode 100644 client/crates/rollkit-client/src/health.rs create mode 100644 client/crates/rollkit-client/src/lib.rs create mode 100644 client/crates/rollkit-client/src/p2p.rs create mode 100644 client/crates/rollkit-client/src/signer.rs create mode 100644 client/crates/rollkit-client/src/store.rs create mode 100644 client/crates/rollkit-client/tests/integration_test.rs rename {crates => client/crates}/rollkit-types/Cargo.toml (100%) rename {crates => client/crates}/rollkit-types/build.rs (82%) rename {crates => client/crates}/rollkit-types/src/lib.rs (100%) rename {crates => client/crates}/rollkit-types/src/proto/rollkit.v1.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 2394d58994..1049fb36cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,12 +149,27 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +[[package]] +name = "cc" +version = "1.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +dependencies = [ + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.1" @@ -201,6 +216,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -208,6 +238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -216,6 +247,34 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -234,10 +293,16 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -300,6 +365,16 @@ version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "byteorder", + "num-traits", +] + [[package]] name = "heck" version = "0.5.0" @@ -411,6 +486,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.174" @@ -423,6 +504,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.27" @@ -473,6 +564,25 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "object" version = "0.36.7" @@ -488,6 +598,35 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -662,6 +801,15 @@ dependencies = [ "getrandom 0.2.16", ] +[[package]] +name = "redox_syscall" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +dependencies = [ + "bitflags 2.9.1", +] + [[package]] name = "regex" version = "1.11.1" @@ -691,6 +839,36 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rollkit-client" +version = "0.1.0" +dependencies = [ + "async-trait", + "futures", + "rollkit-types", + "thiserror", + "tokio", + "tokio-test", + "tonic", + "tower", + "tracing", + "tracing-subscriber", +] + [[package]] name = "rollkit-types" version = "0.1.0" @@ -722,6 +900,37 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.21" @@ -737,6 +946,22 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "serde" version = "1.0.219" @@ -757,12 +982,42 @@ dependencies = [ "syn", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "socket2" version = "0.5.10" @@ -803,6 +1058,35 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "tokio" version = "1.45.1" @@ -813,8 +1097,11 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.52.0", ] @@ -828,6 +1115,27 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -839,6 +1147,19 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-test" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" +dependencies = [ + "async-stream", + "bytes", + "futures-core", + "tokio", + "tokio-stream", +] + [[package]] name = "tokio-util" version = "0.7.15" @@ -871,7 +1192,10 @@ dependencies = [ "percent-encoding", "pin-project", "prost", + "rustls", + "rustls-pemfile", "tokio", + "tokio-rustls", "tokio-stream", "tower", "tower-layer", @@ -900,6 +1224,7 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "hdrhistogram", "indexmap 1.9.3", "pin-project", "pin-project-lite", @@ -930,6 +1255,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -953,6 +1279,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", ] [[package]] @@ -967,6 +1319,18 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "walkdir" version = "2.5.0" @@ -1001,6 +1365,22 @@ dependencies = [ "wit-bindgen-rt", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -1010,6 +1390,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 2527a7c1fc..0c55cec5b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ license = "Apache-2.0" repository = "https://github.com/rollkit/rollkit" [workspace] -members = ["crates/rollkit-types"] +members = ["client/crates/rollkit-types", "client/crates/rollkit-client"] resolver = "2" [workspace.dependencies] diff --git a/client/README.md b/client/README.md new file mode 100644 index 0000000000..d66492ac77 --- /dev/null +++ b/client/README.md @@ -0,0 +1,42 @@ +# Rollkit Client Libraries + +This directory contains client libraries for interacting with Rollkit nodes in various programming languages. + +## Structure + +``` +client/ +├── crates/ # Rust client libraries +│ ├── rollkit-types/ # Generated protobuf types for Rust +│ └── rollkit-client/ # High-level Rust client for gRPC services +└── README.md +``` + +## Rust Client + +The Rust client consists of two crates: + +### rollkit-types + +Contains all the protobuf-generated types and service definitions. This crate is automatically generated from the proto files in `/proto/rollkit/v1/`. + +### rollkit-client + +A high-level client library that provides: +- Easy-to-use wrappers around the gRPC services +- Connection management with configurable timeouts +- Type-safe interfaces +- Comprehensive error handling +- Example usage code + +See the [rollkit-client README](crates/rollkit-client/README.md) for detailed usage instructions. + +## Future Client Libraries + +This directory is structured to support additional client libraries in the future: + +- JavaScript/TypeScript client +- Python client +- Go client + +Each language will have its own subdirectory with generated types and high-level client implementations. \ No newline at end of file diff --git a/client/crates/rollkit-client/Cargo.toml b/client/crates/rollkit-client/Cargo.toml new file mode 100644 index 0000000000..4bd13d35f6 --- /dev/null +++ b/client/crates/rollkit-client/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "rollkit-client" +version = "0.1.0" +edition = "2021" +authors = ["Rollkit Contributors"] +description = "Rust client library for interacting with Rollkit nodes via gRPC" +license = "Apache-2.0" +repository = "https://github.com/rollkit/rollkit" + +[dependencies] +rollkit-types = { path = "../rollkit-types" } +tonic = { workspace = true, features = ["transport", "tls"] } +tokio = { version = "1.45", features = ["full"] } +tower = { version = "0.4", features = ["full"] } +thiserror = "1.0" +tracing = "0.1" +futures = "0.3" +async-trait = "0.1" + +[dev-dependencies] +tokio-test = "0.4" +tracing-subscriber = "0.3" \ No newline at end of file diff --git a/client/crates/rollkit-client/README.md b/client/crates/rollkit-client/README.md new file mode 100644 index 0000000000..f5bc518e20 --- /dev/null +++ b/client/crates/rollkit-client/README.md @@ -0,0 +1,101 @@ +# Rollkit Rust Client + +A Rust client library for interacting with Rollkit nodes via gRPC. + +## Features + +- Full gRPC client implementation for all Rollkit services +- Type-safe interfaces using generated protobuf types +- Async/await support with Tokio +- Connection management with configurable timeouts +- Comprehensive error handling + +## Installation + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +rollkit-client = { path = "path/to/rollkit-client" } +tokio = { version = "1.45", features = ["full"] } +``` + +## Usage + +### Basic Example + +```rust +use rollkit_client::{RollkitClient, HealthClient}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Connect to a Rollkit node + let client = RollkitClient::connect("http://localhost:50051").await?; + + // Check health + let mut health = HealthClient::new(&client); + let is_healthy = health.is_healthy().await?; + println!("Node healthy: {}", is_healthy); + + Ok(()) +} +``` + +### Advanced Configuration + +```rust +use rollkit_client::RollkitClient; +use std::time::Duration; + +let client = RollkitClient::connect_with_config( + "http://localhost:50051", + |endpoint| { + endpoint + .timeout(Duration::from_secs(30)) + .connect_timeout(Duration::from_secs(10)) + .tcp_keepalive(Some(Duration::from_secs(60))) + } +).await?; +``` + +## Services + +The client provides wrappers for all Rollkit gRPC services: + +### Health Service +- `livez()` - Check if the node is alive +- `is_healthy()` - Check if the node is healthy + +### P2P Service +- `get_peer_info()` - Get information about connected peers +- `get_net_info()` - Get network information + +### Signer Service +- `sign(message)` - Sign a message +- `get_public_key()` - Get the node's public key + +### Store Service +- `get_block(height)` - Get a block by height +- `get_state(height)` - Get state at a specific height +- `get_metadata(initial_height, latest_height)` - Get metadata for a height range + +## Examples + +See the `examples` directory for more detailed usage examples: + +```bash +cargo run --example basic +``` + +## Error Handling + +All methods return `Result` where `RollkitClientError` encompasses: +- Transport errors +- RPC errors +- Connection errors +- Invalid endpoint errors +- Timeout errors + +## License + +Apache-2.0 \ No newline at end of file diff --git a/client/crates/rollkit-client/examples/basic.rs b/client/crates/rollkit-client/examples/basic.rs new file mode 100644 index 0000000000..7763151270 --- /dev/null +++ b/client/crates/rollkit-client/examples/basic.rs @@ -0,0 +1,109 @@ +use rollkit_client::{RollkitClient, HealthClient, P2PClient, SignerClient, StoreClient}; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Initialize tracing for better debugging + tracing_subscriber::fmt::init(); + + // Connect to a Rollkit node + let endpoint = std::env::var("ROLLKIT_ENDPOINT").unwrap_or_else(|_| "http://localhost:50051".to_string()); + println!("Connecting to Rollkit node at: {}", endpoint); + + let client = RollkitClient::connect(&endpoint).await?; + println!("Successfully connected to Rollkit node"); + + // Check health status + println!("\n=== Health Check ==="); + let mut health = HealthClient::new(&client); + match health.get_health().await { + Ok(health_response) => { + println!("Health status: {:?}", health_response.status()); + println!("Node is healthy: {}", health.is_healthy().await?); + } + Err(e) => println!("Failed to get health status: {}", e), + } + + // Get P2P information + println!("\n=== P2P Information ==="); + let mut p2p = P2PClient::new(&client); + match p2p.get_net_info().await { + Ok(net_info) => { + println!("Network ID: {}", net_info.id); + println!("Listen addresses: {:?}", net_info.listen_addresses); + println!("Connected peers: {:?}", net_info.connected_peers); + } + Err(e) => println!("Failed to get network info: {}", e), + } + + match p2p.get_peer_info().await { + Ok(peers) => { + println!("Number of peers: {}", peers.len()); + for peer in peers { + println!(" Peer ID: {}, Address: {}", peer.id, peer.address); + } + } + Err(e) => println!("Failed to get peer info: {}", e), + } + + // Get signer information + println!("\n=== Signer Information ==="); + let mut signer = SignerClient::new(&client); + match signer.get_public_key().await { + Ok(pubkey) => { + println!("Public key (hex): {}", hex::encode(&pubkey)); + } + Err(e) => println!("Failed to get public key: {}", e), + } + + // Example: Sign a message + let message = b"Hello, Rollkit!"; + match signer.sign(message.to_vec()).await { + Ok(signature) => { + println!("Message signed successfully"); + println!("Signature (hex): {}", hex::encode(&signature)); + } + Err(e) => println!("Failed to sign message: {}", e), + } + + // Get store information + println!("\n=== Store Information ==="); + let mut store = StoreClient::new(&client); + + // Try to get the latest block (height 0 for genesis) + match store.get_block_by_height(0).await { + Ok(Some(block)) => { + println!("Genesis block found:"); + println!(" Height: {}", block.header.as_ref().map(|h| h.header.as_ref().map(|hdr| hdr.height).unwrap_or(0)).unwrap_or(0)); + } + Ok(None) => println!("No block found at height 0"), + Err(e) => println!("Failed to get block: {}", e), + } + + // Get current state + match store.get_state().await { + Ok(Some(state)) => { + println!("Current state found"); + println!(" Last block height: {}", state.last_block_height); + } + Ok(None) => println!("No state found"), + Err(e) => println!("Failed to get state: {}", e), + } + + // Get metadata by key + match store.get_metadata("test_key".to_string()).await { + Ok(value) => { + println!("Metadata value: {}", hex::encode(&value)); + } + Err(e) => println!("Failed to get metadata: {}", e), + } + + Ok(()) +} + +// Helper function to encode bytes as hex (you'll need to add 'hex' to dev-dependencies) +mod hex { + pub fn encode(bytes: &[u8]) -> String { + bytes.iter().map(|b| format!("{:02x}", b)).collect() + } +} \ No newline at end of file diff --git a/client/crates/rollkit-client/src/client.rs b/client/crates/rollkit-client/src/client.rs new file mode 100644 index 0000000000..0d427dece1 --- /dev/null +++ b/client/crates/rollkit-client/src/client.rs @@ -0,0 +1,64 @@ +use crate::error::{Result, RollkitClientError}; +use std::time::Duration; +use tonic::transport::{Channel, Endpoint}; + +#[derive(Clone, Debug)] +pub struct RollkitClient { + channel: Channel, + endpoint: String, +} + +impl RollkitClient { + /// Create a new RollkitClient with the given endpoint + pub async fn connect(endpoint: impl Into) -> Result { + let endpoint = endpoint.into(); + let channel = Self::create_channel(&endpoint).await?; + + Ok(Self { channel, endpoint }) + } + + /// Create a new RollkitClient with custom channel configuration + pub async fn connect_with_config(endpoint: impl Into, config: F) -> Result + where + F: FnOnce(Endpoint) -> Endpoint, + { + let endpoint_str = endpoint.into(); + let endpoint = Endpoint::from_shared(endpoint_str.clone()) + .map_err(|e| RollkitClientError::InvalidEndpoint(e.to_string()))?; + + let endpoint = config(endpoint); + let channel = endpoint + .connect() + .await + .map_err(RollkitClientError::Transport)?; + + Ok(Self { + channel, + endpoint: endpoint_str, + }) + } + + /// Get the underlying channel + pub fn channel(&self) -> &Channel { + &self.channel + } + + /// Get the endpoint URL + pub fn endpoint(&self) -> &str { + &self.endpoint + } + + async fn create_channel(endpoint: &str) -> Result { + let endpoint = Endpoint::from_shared(endpoint.to_string()) + .map_err(|e| RollkitClientError::InvalidEndpoint(e.to_string()))? + .timeout(Duration::from_secs(10)) + .connect_timeout(Duration::from_secs(5)); + + let channel = endpoint + .connect() + .await + .map_err(RollkitClientError::Transport)?; + + Ok(channel) + } +} \ No newline at end of file diff --git a/client/crates/rollkit-client/src/error.rs b/client/crates/rollkit-client/src/error.rs new file mode 100644 index 0000000000..033f3dce82 --- /dev/null +++ b/client/crates/rollkit-client/src/error.rs @@ -0,0 +1,21 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum RollkitClientError { + #[error("Transport error: {0}")] + Transport(#[from] tonic::transport::Error), + + #[error("RPC error: {0}")] + Rpc(#[from] tonic::Status), + + #[error("Connection error: {0}")] + Connection(String), + + #[error("Invalid endpoint: {0}")] + InvalidEndpoint(String), + + #[error("Timeout error")] + Timeout, +} + +pub type Result = std::result::Result; \ No newline at end of file diff --git a/client/crates/rollkit-client/src/health.rs b/client/crates/rollkit-client/src/health.rs new file mode 100644 index 0000000000..c641166126 --- /dev/null +++ b/client/crates/rollkit-client/src/health.rs @@ -0,0 +1,40 @@ +use crate::{client::RollkitClient, error::Result}; +use rollkit_types::v1::{ + health_service_client::HealthServiceClient, + GetHealthResponse, HealthStatus, +}; +use tonic::Request; + +pub struct HealthClient { + inner: HealthServiceClient, +} + +impl HealthClient { + /// Create a new HealthClient from a RollkitClient + pub fn new(client: &RollkitClient) -> Self { + let inner = HealthServiceClient::new(client.channel().clone()); + Self { inner } + } + + /// Check if the node is alive and get its health status + pub async fn livez(&mut self) -> Result { + let request = Request::new(()); + let response = self.inner.livez(request).await?; + + Ok(response.into_inner().status()) + } + + /// Get the full health response + pub async fn get_health(&mut self) -> Result { + let request = Request::new(()); + let response = self.inner.livez(request).await?; + + Ok(response.into_inner()) + } + + /// Check if the node is healthy (status is PASS) + pub async fn is_healthy(&mut self) -> Result { + let status = self.livez().await?; + Ok(status == HealthStatus::Pass) + } +} \ No newline at end of file diff --git a/client/crates/rollkit-client/src/lib.rs b/client/crates/rollkit-client/src/lib.rs new file mode 100644 index 0000000000..7afb05ea92 --- /dev/null +++ b/client/crates/rollkit-client/src/lib.rs @@ -0,0 +1,40 @@ +//! Rollkit Rust Client Library +//! +//! This library provides a Rust client for interacting with Rollkit nodes via gRPC. +//! +//! # Example +//! +//! ```no_run +//! use rollkit_client::{RollkitClient, HealthClient}; +//! +//! #[tokio::main] +//! async fn main() -> Result<(), Box> { +//! // Connect to a Rollkit node +//! let client = RollkitClient::connect("http://localhost:50051").await?; +//! +//! // Check health +//! let mut health = HealthClient::new(&client); +//! let is_healthy = health.is_healthy().await?; +//! println!("Node healthy: {}", is_healthy); +//! +//! Ok(()) +//! } +//! ``` + +pub mod client; +pub mod error; +pub mod health; +pub mod p2p; +pub mod signer; +pub mod store; + +// Re-export main types for convenience +pub use client::RollkitClient; +pub use error::{RollkitClientError, Result}; +pub use health::HealthClient; +pub use p2p::P2PClient; +pub use signer::SignerClient; +pub use store::StoreClient; + +// Re-export types from rollkit-types for convenience +pub use rollkit_types::v1; \ No newline at end of file diff --git a/client/crates/rollkit-client/src/p2p.rs b/client/crates/rollkit-client/src/p2p.rs new file mode 100644 index 0000000000..63a91cb5a7 --- /dev/null +++ b/client/crates/rollkit-client/src/p2p.rs @@ -0,0 +1,56 @@ +use crate::{client::RollkitClient, error::Result}; +use rollkit_types::v1::{ + p2p_service_client::P2pServiceClient, + GetNetInfoResponse, GetPeerInfoResponse, NetInfo, PeerInfo, +}; +use tonic::Request; + +pub struct P2PClient { + inner: P2pServiceClient, +} + +impl P2PClient { + /// Create a new P2PClient from a RollkitClient + pub fn new(client: &RollkitClient) -> Self { + let inner = P2pServiceClient::new(client.channel().clone()); + Self { inner } + } + + /// Get information about connected peers + pub async fn get_peer_info(&mut self) -> Result> { + let request = Request::new(()); + let response = self.inner.get_peer_info(request).await?; + + Ok(response.into_inner().peers) + } + + /// Get network information + pub async fn get_net_info(&mut self) -> Result { + let request = Request::new(()); + let response = self.inner.get_net_info(request).await?; + + Ok(response.into_inner().net_info.unwrap_or_default()) + } + + /// Get the full peer info response + pub async fn get_peer_info_response(&mut self) -> Result { + let request = Request::new(()); + let response = self.inner.get_peer_info(request).await?; + + Ok(response.into_inner()) + } + + /// Get the full network info response + pub async fn get_net_info_response(&mut self) -> Result { + let request = Request::new(()); + let response = self.inner.get_net_info(request).await?; + + Ok(response.into_inner()) + } + + /// Get the number of connected peers + pub async fn peer_count(&mut self) -> Result { + let peers = self.get_peer_info().await?; + Ok(peers.len()) + } +} \ No newline at end of file diff --git a/client/crates/rollkit-client/src/signer.rs b/client/crates/rollkit-client/src/signer.rs new file mode 100644 index 0000000000..8231dace13 --- /dev/null +++ b/client/crates/rollkit-client/src/signer.rs @@ -0,0 +1,50 @@ +use crate::{client::RollkitClient, error::Result}; +use rollkit_types::v1::{ + signer_service_client::SignerServiceClient, + SignRequest, SignResponse, GetPublicRequest, GetPublicResponse, +}; +use tonic::Request; + +pub struct SignerClient { + inner: SignerServiceClient, +} + +impl SignerClient { + /// Create a new SignerClient from a RollkitClient + pub fn new(client: &RollkitClient) -> Self { + let inner = SignerServiceClient::new(client.channel().clone()); + Self { inner } + } + + /// Sign a message + pub async fn sign(&mut self, message: Vec) -> Result> { + let request = Request::new(SignRequest { message }); + let response = self.inner.sign(request).await?; + + Ok(response.into_inner().signature) + } + + /// Get the public key + pub async fn get_public_key(&mut self) -> Result> { + let request = Request::new(GetPublicRequest {}); + let response = self.inner.get_public(request).await?; + + Ok(response.into_inner().public_key) + } + + /// Get the full sign response + pub async fn sign_full(&mut self, message: Vec) -> Result { + let request = Request::new(SignRequest { message }); + let response = self.inner.sign(request).await?; + + Ok(response.into_inner()) + } + + /// Get the full public key response + pub async fn get_public_full(&mut self) -> Result { + let request = Request::new(GetPublicRequest {}); + let response = self.inner.get_public(request).await?; + + Ok(response.into_inner()) + } +} \ No newline at end of file diff --git a/client/crates/rollkit-client/src/store.rs b/client/crates/rollkit-client/src/store.rs new file mode 100644 index 0000000000..dc19650c7a --- /dev/null +++ b/client/crates/rollkit-client/src/store.rs @@ -0,0 +1,93 @@ +use crate::{client::RollkitClient, error::Result}; +use rollkit_types::v1::{ + store_service_client::StoreServiceClient, + Block, GetBlockRequest, GetBlockResponse, + GetStateResponse, GetMetadataRequest, GetMetadataResponse, + get_block_request::Identifier, + State, +}; +use tonic::Request; + +pub struct StoreClient { + inner: StoreServiceClient, +} + +impl StoreClient { + /// Create a new StoreClient from a RollkitClient + pub fn new(client: &RollkitClient) -> Self { + let inner = StoreServiceClient::new(client.channel().clone()); + Self { inner } + } + + /// Get a block by height + pub async fn get_block_by_height(&mut self, height: u64) -> Result> { + let request = Request::new(GetBlockRequest { + identifier: Some(Identifier::Height(height)), + }); + let response = self.inner.get_block(request).await?; + + Ok(response.into_inner().block) + } + + /// Get a block by hash + pub async fn get_block_by_hash(&mut self, hash: Vec) -> Result> { + let request = Request::new(GetBlockRequest { + identifier: Some(Identifier::Hash(hash)), + }); + let response = self.inner.get_block(request).await?; + + Ok(response.into_inner().block) + } + + /// Get the current state + pub async fn get_state(&mut self) -> Result> { + let request = Request::new(()); + let response = self.inner.get_state(request).await?; + + Ok(response.into_inner().state) + } + + /// Get metadata by key + pub async fn get_metadata(&mut self, key: String) -> Result> { + let request = Request::new(GetMetadataRequest { key }); + let response = self.inner.get_metadata(request).await?; + + Ok(response.into_inner().value) + } + + /// Get the full block response by height + pub async fn get_block_full_by_height(&mut self, height: u64) -> Result { + let request = Request::new(GetBlockRequest { + identifier: Some(Identifier::Height(height)), + }); + let response = self.inner.get_block(request).await?; + + Ok(response.into_inner()) + } + + /// Get the full block response by hash + pub async fn get_block_full_by_hash(&mut self, hash: Vec) -> Result { + let request = Request::new(GetBlockRequest { + identifier: Some(Identifier::Hash(hash)), + }); + let response = self.inner.get_block(request).await?; + + Ok(response.into_inner()) + } + + /// Get the full state response + pub async fn get_state_full(&mut self) -> Result { + let request = Request::new(()); + let response = self.inner.get_state(request).await?; + + Ok(response.into_inner()) + } + + /// Get the full metadata response + pub async fn get_metadata_full(&mut self, key: String) -> Result { + let request = Request::new(GetMetadataRequest { key }); + let response = self.inner.get_metadata(request).await?; + + Ok(response.into_inner()) + } +} \ No newline at end of file diff --git a/client/crates/rollkit-client/tests/integration_test.rs b/client/crates/rollkit-client/tests/integration_test.rs new file mode 100644 index 0000000000..8fba9b37db --- /dev/null +++ b/client/crates/rollkit-client/tests/integration_test.rs @@ -0,0 +1,35 @@ +use rollkit_client::{RollkitClient, RollkitClientError}; + +#[tokio::test] +async fn test_client_creation() { + // Test creating a client with an invalid endpoint - will fail during connection + let result = RollkitClient::connect("http://localhost:12345").await; + assert!(result.is_err()); + + match result.unwrap_err() { + RollkitClientError::Transport(_) => {} + e => panic!("Expected Transport error, got: {:?}", e), + } +} + +#[tokio::test] +async fn test_client_with_config() { + use std::time::Duration; + + // Test creating a client with custom configuration + let result = RollkitClient::connect_with_config( + "http://localhost:50051", + |endpoint| { + endpoint + .timeout(Duration::from_secs(5)) + .connect_timeout(Duration::from_secs(2)) + } + ).await; + + // This will fail to connect since no server is running, but it should be a transport error + assert!(result.is_err()); + match result.unwrap_err() { + RollkitClientError::Transport(_) => {} + _ => panic!("Expected Transport error"), + } +} \ No newline at end of file diff --git a/crates/rollkit-types/Cargo.toml b/client/crates/rollkit-types/Cargo.toml similarity index 100% rename from crates/rollkit-types/Cargo.toml rename to client/crates/rollkit-types/Cargo.toml diff --git a/crates/rollkit-types/build.rs b/client/crates/rollkit-types/build.rs similarity index 82% rename from crates/rollkit-types/build.rs rename to client/crates/rollkit-types/build.rs index 25cf8aa50a..61977f3ab1 100644 --- a/crates/rollkit-types/build.rs +++ b/client/crates/rollkit-types/build.rs @@ -3,7 +3,7 @@ use walkdir::WalkDir; // Collect all .proto files recursively under /proto/ and compile. fn main() -> Result<(), Box> { - let proto_files: Vec = WalkDir::new("../../proto") + let proto_files: Vec = WalkDir::new("../../../proto") .into_iter() .filter_map(|entry| { let path = entry.ok()?.path().to_path_buf(); @@ -19,7 +19,7 @@ fn main() -> Result<(), Box> { .build_server(true) .build_client(true) .out_dir("src/proto") - .compile(&proto_files, &["../../proto"])?; + .compile(&proto_files, &["../../../proto"])?; Ok(()) } diff --git a/crates/rollkit-types/src/lib.rs b/client/crates/rollkit-types/src/lib.rs similarity index 100% rename from crates/rollkit-types/src/lib.rs rename to client/crates/rollkit-types/src/lib.rs diff --git a/crates/rollkit-types/src/proto/rollkit.v1.rs b/client/crates/rollkit-types/src/proto/rollkit.v1.rs similarity index 100% rename from crates/rollkit-types/src/proto/rollkit.v1.rs rename to client/crates/rollkit-types/src/proto/rollkit.v1.rs From 785442d2edf18d15c0630dc5d692675b529284a3 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 2 Jul 2025 15:29:50 +0200 Subject: [PATCH 05/16] add ci --- .github/actions/rust-setup/action.yml | 51 +++++++++++ .github/workflows/rust-ci-status.yml | 24 +++++ .github/workflows/rust-lint.yml | 116 ++++++++++++++++++++++++ .github/workflows/rust-proto-check.yml | 100 ++++++++++++++++++++ .github/workflows/rust-publish.yml | 98 ++++++++++++++++++++ .github/workflows/rust-test.yml | 88 ++++++++++++++++++ client/crates/rollkit-client/Cargo.toml | 4 + client/crates/rollkit-client/README.md | 5 + client/crates/rollkit-types/Cargo.toml | 8 ++ 9 files changed, 494 insertions(+) create mode 100644 .github/actions/rust-setup/action.yml create mode 100644 .github/workflows/rust-ci-status.yml create mode 100644 .github/workflows/rust-lint.yml create mode 100644 .github/workflows/rust-proto-check.yml create mode 100644 .github/workflows/rust-publish.yml create mode 100644 .github/workflows/rust-test.yml diff --git a/.github/actions/rust-setup/action.yml b/.github/actions/rust-setup/action.yml new file mode 100644 index 0000000000..29f734e0d7 --- /dev/null +++ b/.github/actions/rust-setup/action.yml @@ -0,0 +1,51 @@ +name: 'Setup Rust' +description: 'Setup Rust toolchain with caching and protoc' +inputs: + toolchain: + description: 'Rust toolchain to install' + required: false + default: 'stable' + components: + description: 'Rust components to install' + required: false + default: '' + cache-key: + description: 'Additional cache key for dependencies' + required: false + default: 'default' + +runs: + using: 'composite' + steps: + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ inputs.toolchain }} + components: ${{ inputs.components }} + + - name: Install protoc + uses: arduino/setup-protoc@v3 + with: + version: "25.1" + repo-token: ${{ github.token }} + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ inputs.toolchain }}-${{ inputs.cache-key }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-${{ inputs.toolchain }}-${{ inputs.cache-key }}- + ${{ runner.os }}-cargo-${{ inputs.toolchain }}- + + - name: Display Rust version + shell: bash + run: | + rustc --version + cargo --version + protoc --version \ No newline at end of file diff --git a/.github/workflows/rust-ci-status.yml b/.github/workflows/rust-ci-status.yml new file mode 100644 index 0000000000..60eab8185f --- /dev/null +++ b/.github/workflows/rust-ci-status.yml @@ -0,0 +1,24 @@ +name: Rust CI Status + +on: + workflow_run: + workflows: ["Rust Tests", "Rust Lint", "Rust Proto Generation Check"] + types: + - completed + +jobs: + status: + name: Update CI Status + runs-on: ubuntu-latest + if: github.event.workflow_run.conclusion != 'skipped' + steps: + - name: Report status + run: | + echo "Workflow: ${{ github.event.workflow_run.name }}" + echo "Status: ${{ github.event.workflow_run.conclusion }}" + echo "Branch: ${{ github.event.workflow_run.head_branch }}" + + if [ "${{ github.event.workflow_run.conclusion }}" != "success" ]; then + echo "::error::Rust CI workflow failed" + exit 1 + fi \ No newline at end of file diff --git a/.github/workflows/rust-lint.yml b/.github/workflows/rust-lint.yml new file mode 100644 index 0000000000..51962ec22f --- /dev/null +++ b/.github/workflows/rust-lint.yml @@ -0,0 +1,116 @@ +name: Rust Lint + +on: + pull_request: + paths: + - 'client/**' + - 'proto/**' + - 'Cargo.toml' + - 'Cargo.lock' + - '.github/workflows/rust-*.yml' + push: + branches: + - main + - release/* + paths: + - 'client/**' + - 'proto/**' + - 'Cargo.toml' + - 'Cargo.lock' + - '.github/workflows/rust-*.yml' + +jobs: + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + + - name: Check formatting + run: cargo fmt --all -- --check + + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - name: Install protoc + uses: arduino/setup-protoc@v3 + with: + version: "25.1" + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-clippy-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-clippy- + + - name: Run clippy + run: cargo clippy --workspace --all-features -- -D warnings + + audit: + name: Security Audit + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run cargo audit + uses: actions-rust-lang/audit@v1 + with: + ignore: "" # Add RUSTSEC IDs to ignore if needed + + docs: + name: Documentation + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Install protoc + uses: arduino/setup-protoc@v3 + with: + version: "25.1" + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-doc-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-doc- + + - name: Check documentation + run: cargo doc --workspace --no-deps --all-features + env: + RUSTDOCFLAGS: -D warnings \ No newline at end of file diff --git a/.github/workflows/rust-proto-check.yml b/.github/workflows/rust-proto-check.yml new file mode 100644 index 0000000000..d38625ca19 --- /dev/null +++ b/.github/workflows/rust-proto-check.yml @@ -0,0 +1,100 @@ +name: Rust Proto Generation Check + +on: + pull_request: + paths: + - 'proto/**' + - 'client/crates/rollkit-types/build.rs' + - 'client/crates/rollkit-types/src/proto/**' + - '.github/workflows/rust-proto-check.yml' + push: + branches: + - main + - release/* + paths: + - 'proto/**' + - 'client/crates/rollkit-types/build.rs' + - 'client/crates/rollkit-types/src/proto/**' + - '.github/workflows/rust-proto-check.yml' + +jobs: + check-proto-generation: + name: Check Proto Generation + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Install protoc + uses: arduino/setup-protoc@v3 + with: + version: "25.1" + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-proto-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-proto- + + - name: Remove existing generated files + run: | + rm -rf client/crates/rollkit-types/src/proto/*.rs + + - name: Generate proto files + run: | + cd client/crates/rollkit-types + cargo build + + - name: Check for uncommitted changes + run: | + if ! git diff --exit-code client/crates/rollkit-types/src/proto/; then + echo "::error::Generated proto files are not up to date. Please run 'cargo build' in client/crates/rollkit-types and commit the changes." + echo "Differences found:" + git diff client/crates/rollkit-types/src/proto/ + exit 1 + fi + + proto-breaking-changes: + name: Check Proto Breaking Changes + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install buf + uses: bufbuild/buf-setup-action@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Check for breaking changes + run: | + # Create buf.yaml if it doesn't exist + if [ ! -f buf.yaml ]; then + cat > buf.yaml << EOF + version: v1 + breaking: + use: + - FILE + lint: + use: + - DEFAULT + EOF + fi + + # Check for breaking changes against main branch + git fetch origin main + buf breaking proto --against .git#branch=origin/main,subdir=proto || echo "::warning::Breaking changes detected in proto files" \ No newline at end of file diff --git a/.github/workflows/rust-publish.yml b/.github/workflows/rust-publish.yml new file mode 100644 index 0000000000..b0ef39fcc9 --- /dev/null +++ b/.github/workflows/rust-publish.yml @@ -0,0 +1,98 @@ +name: Publish Rust Crates + +on: + push: + tags: + - 'rust-v*' + workflow_dispatch: + inputs: + dry_run: + description: 'Perform a dry run without publishing' + required: false + type: boolean + default: true + +jobs: + publish: + name: Publish to crates.io + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Rust + uses: ./.github/actions/rust-setup + with: + cache-key: publish + + - name: Check crate versions + run: | + echo "=== Checking crate versions ===" + echo "rollkit-types version: $(cargo pkgid -p rollkit-types | cut -d# -f2)" + echo "rollkit-client version: $(cargo pkgid -p rollkit-client | cut -d# -f2)" + + - name: Run tests + run: cargo test --workspace --all-features + + - name: Package crates + run: | + cargo package -p rollkit-types --allow-dirty + cargo package -p rollkit-client --allow-dirty + + - name: Publish rollkit-types (dry run) + if: github.event_name == 'workflow_dispatch' && inputs.dry_run + run: | + cd client/crates/rollkit-types + cargo publish --dry-run + + - name: Publish rollkit-client (dry run) + if: github.event_name == 'workflow_dispatch' && inputs.dry_run + run: | + cd client/crates/rollkit-client + cargo publish --dry-run + + - name: Publish rollkit-types + if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && !inputs.dry_run) + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: | + cd client/crates/rollkit-types + cargo publish + + - name: Wait for rollkit-types to be available + if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && !inputs.dry_run) + run: | + echo "Waiting for rollkit-types to be available on crates.io..." + sleep 30 + + - name: Publish rollkit-client + if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && !inputs.dry_run) + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: | + cd client/crates/rollkit-client + cargo publish + + - name: Create GitHub Release + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v2 + with: + name: Rust Client ${{ github.ref_name }} + body: | + # Rust Client Release + + This release includes: + - `rollkit-types`: Proto-generated types for Rollkit + - `rollkit-client`: High-level Rust client for Rollkit gRPC services + + ## Installation + + Add to your `Cargo.toml`: + ```toml + [dependencies] + rollkit-client = "" + ``` + + See the [README](https://github.com/rollkit/rollkit/tree/main/client/crates/rollkit-client) for usage examples. + draft: false + prerelease: false \ No newline at end of file diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml new file mode 100644 index 0000000000..74d808dcdf --- /dev/null +++ b/.github/workflows/rust-test.yml @@ -0,0 +1,88 @@ +name: Rust Tests + +on: + pull_request: + paths: + - 'client/**' + - 'proto/**' + - 'Cargo.toml' + - 'Cargo.lock' + - '.github/workflows/rust-*.yml' + push: + branches: + - main + - release/* + paths: + - 'client/**' + - 'proto/**' + - 'Cargo.toml' + - 'Cargo.lock' + - '.github/workflows/rust-*.yml' + +jobs: + test: + name: Test Rust Client + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - beta + - nightly + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Rust + uses: ./.github/actions/rust-setup + with: + toolchain: ${{ matrix.rust }} + components: rustfmt, clippy + cache-key: test + + - name: Build + run: cargo build --workspace --all-features --verbose + + - name: Run tests + run: cargo test --workspace --all-features --verbose + + - name: Run doc tests + run: cargo test --workspace --doc --verbose + + - name: Check examples + run: | + cd client/crates/rollkit-client + cargo check --examples --verbose + + coverage: + name: Code Coverage + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: llvm-tools-preview + + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov + + - name: Install protoc + uses: arduino/setup-protoc@v3 + with: + version: "25.1" + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Generate code coverage + run: cargo llvm-cov --workspace --lcov --output-path lcov.info + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + files: lcov.info + flags: rust + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/client/crates/rollkit-client/Cargo.toml b/client/crates/rollkit-client/Cargo.toml index 4bd13d35f6..24205ae357 100644 --- a/client/crates/rollkit-client/Cargo.toml +++ b/client/crates/rollkit-client/Cargo.toml @@ -6,6 +6,10 @@ authors = ["Rollkit Contributors"] description = "Rust client library for interacting with Rollkit nodes via gRPC" license = "Apache-2.0" repository = "https://github.com/rollkit/rollkit" +homepage = "https://rollkit.dev" +documentation = "https://docs.rs/rollkit-client" +keywords = ["rollkit", "blockchain", "client", "grpc", "api"] +categories = ["api-bindings", "network-programming"] [dependencies] rollkit-types = { path = "../rollkit-types" } diff --git a/client/crates/rollkit-client/README.md b/client/crates/rollkit-client/README.md index f5bc518e20..33d415e859 100644 --- a/client/crates/rollkit-client/README.md +++ b/client/crates/rollkit-client/README.md @@ -1,5 +1,10 @@ # Rollkit Rust Client +[![Rust Tests](https://github.com/rollkit/rollkit/actions/workflows/rust-test.yml/badge.svg)](https://github.com/rollkit/rollkit/actions/workflows/rust-test.yml) +[![Rust Lint](https://github.com/rollkit/rollkit/actions/workflows/rust-lint.yml/badge.svg)](https://github.com/rollkit/rollkit/actions/workflows/rust-lint.yml) +[![crates.io](https://img.shields.io/crates/v/rollkit-client.svg)](https://crates.io/crates/rollkit-client) +[![docs.rs](https://docs.rs/rollkit-client/badge.svg)](https://docs.rs/rollkit-client) + A Rust client library for interacting with Rollkit nodes via gRPC. ## Features diff --git a/client/crates/rollkit-types/Cargo.toml b/client/crates/rollkit-types/Cargo.toml index f131f16952..b579345b85 100644 --- a/client/crates/rollkit-types/Cargo.toml +++ b/client/crates/rollkit-types/Cargo.toml @@ -2,6 +2,14 @@ name = "rollkit-types" version = "0.1.0" edition = "2021" +authors = ["Rollkit Contributors"] +description = "Protocol buffer generated types for Rollkit" +documentation = "https://docs.rs/rollkit-types" +homepage = "https://rollkit.dev" +repository = "https://github.com/rollkit/rollkit" +license = "Apache-2.0" +keywords = ["rollkit", "blockchain", "protobuf", "grpc"] +categories = ["api-bindings", "encoding"] [build-dependencies] tonic-build = { workspace = true } From be240a04b07f737a42100659781d80172c1a2e5c Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 2 Jul 2025 15:31:36 +0200 Subject: [PATCH 06/16] fixes --- .github/workflows/rust-lint.yml | 20 +++++++------------- .github/workflows/rust-proto-check.yml | 17 ++++++----------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/.github/workflows/rust-lint.yml b/.github/workflows/rust-lint.yml index 51962ec22f..68de402c28 100644 --- a/.github/workflows/rust-lint.yml +++ b/.github/workflows/rust-lint.yml @@ -3,21 +3,15 @@ name: Rust Lint on: pull_request: paths: - - 'client/**' - - 'proto/**' - - 'Cargo.toml' - - 'Cargo.lock' - - '.github/workflows/rust-*.yml' + - "client/**" + - "proto/**" + - "Cargo.toml" + - "Cargo.lock" + - ".github/workflows/rust-*.yml" push: branches: - main - release/* - paths: - - 'client/**' - - 'proto/**' - - 'Cargo.toml' - - 'Cargo.lock' - - '.github/workflows/rust-*.yml' jobs: fmt: @@ -79,7 +73,7 @@ jobs: - name: Run cargo audit uses: actions-rust-lang/audit@v1 with: - ignore: "" # Add RUSTSEC IDs to ignore if needed + ignore: "" # Add RUSTSEC IDs to ignore if needed docs: name: Documentation @@ -113,4 +107,4 @@ jobs: - name: Check documentation run: cargo doc --workspace --no-deps --all-features env: - RUSTDOCFLAGS: -D warnings \ No newline at end of file + RUSTDOCFLAGS: -D warnings diff --git a/.github/workflows/rust-proto-check.yml b/.github/workflows/rust-proto-check.yml index d38625ca19..06bda400fc 100644 --- a/.github/workflows/rust-proto-check.yml +++ b/.github/workflows/rust-proto-check.yml @@ -3,19 +3,14 @@ name: Rust Proto Generation Check on: pull_request: paths: - - 'proto/**' - - 'client/crates/rollkit-types/build.rs' - - 'client/crates/rollkit-types/src/proto/**' - - '.github/workflows/rust-proto-check.yml' + - "proto/**" + - "client/crates/rollkit-types/build.rs" + - "client/crates/rollkit-types/src/proto/**" + - ".github/workflows/rust-proto-check.yml" push: branches: - main - release/* - paths: - - 'proto/**' - - 'client/crates/rollkit-types/build.rs' - - 'client/crates/rollkit-types/src/proto/**' - - '.github/workflows/rust-proto-check.yml' jobs: check-proto-generation: @@ -94,7 +89,7 @@ jobs: - DEFAULT EOF fi - + # Check for breaking changes against main branch git fetch origin main - buf breaking proto --against .git#branch=origin/main,subdir=proto || echo "::warning::Breaking changes detected in proto files" \ No newline at end of file + buf breaking proto --against .git#branch=origin/main,subdir=proto || echo "::warning::Breaking changes detected in proto files" From ef850ec71fcde71412cf00c03676637ec9d32fd0 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 2 Jul 2025 15:35:27 +0200 Subject: [PATCH 07/16] fix format --- .../crates/rollkit-client/examples/basic.rs | 40 +++++++++++-------- client/crates/rollkit-client/src/client.rs | 20 +++++----- client/crates/rollkit-client/src/error.rs | 10 ++--- client/crates/rollkit-client/src/health.rs | 15 ++++--- client/crates/rollkit-client/src/lib.rs | 12 +++--- client/crates/rollkit-client/src/p2p.rs | 24 +++++------ client/crates/rollkit-client/src/signer.rs | 22 +++++----- client/crates/rollkit-client/src/store.rs | 40 +++++++++---------- .../rollkit-client/tests/integration_test.rs | 22 +++++----- 9 files changed, 104 insertions(+), 101 deletions(-) diff --git a/client/crates/rollkit-client/examples/basic.rs b/client/crates/rollkit-client/examples/basic.rs index 7763151270..f58644dfdf 100644 --- a/client/crates/rollkit-client/examples/basic.rs +++ b/client/crates/rollkit-client/examples/basic.rs @@ -1,18 +1,19 @@ -use rollkit_client::{RollkitClient, HealthClient, P2PClient, SignerClient, StoreClient}; +use rollkit_client::{HealthClient, P2PClient, RollkitClient, SignerClient, StoreClient}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { // Initialize tracing for better debugging tracing_subscriber::fmt::init(); - + // Connect to a Rollkit node - let endpoint = std::env::var("ROLLKIT_ENDPOINT").unwrap_or_else(|_| "http://localhost:50051".to_string()); + let endpoint = + std::env::var("ROLLKIT_ENDPOINT").unwrap_or_else(|_| "http://localhost:50051".to_string()); println!("Connecting to Rollkit node at: {}", endpoint); - + let client = RollkitClient::connect(&endpoint).await?; println!("Successfully connected to Rollkit node"); - + // Check health status println!("\n=== Health Check ==="); let mut health = HealthClient::new(&client); @@ -23,7 +24,7 @@ async fn main() -> Result<(), Box> { } Err(e) => println!("Failed to get health status: {}", e), } - + // Get P2P information println!("\n=== P2P Information ==="); let mut p2p = P2PClient::new(&client); @@ -35,7 +36,7 @@ async fn main() -> Result<(), Box> { } Err(e) => println!("Failed to get network info: {}", e), } - + match p2p.get_peer_info().await { Ok(peers) => { println!("Number of peers: {}", peers.len()); @@ -45,7 +46,7 @@ async fn main() -> Result<(), Box> { } Err(e) => println!("Failed to get peer info: {}", e), } - + // Get signer information println!("\n=== Signer Information ==="); let mut signer = SignerClient::new(&client); @@ -55,7 +56,7 @@ async fn main() -> Result<(), Box> { } Err(e) => println!("Failed to get public key: {}", e), } - + // Example: Sign a message let message = b"Hello, Rollkit!"; match signer.sign(message.to_vec()).await { @@ -65,21 +66,28 @@ async fn main() -> Result<(), Box> { } Err(e) => println!("Failed to sign message: {}", e), } - + // Get store information println!("\n=== Store Information ==="); let mut store = StoreClient::new(&client); - + // Try to get the latest block (height 0 for genesis) match store.get_block_by_height(0).await { Ok(Some(block)) => { println!("Genesis block found:"); - println!(" Height: {}", block.header.as_ref().map(|h| h.header.as_ref().map(|hdr| hdr.height).unwrap_or(0)).unwrap_or(0)); + println!( + " Height: {}", + block + .header + .as_ref() + .map(|h| h.header.as_ref().map(|hdr| hdr.height).unwrap_or(0)) + .unwrap_or(0) + ); } Ok(None) => println!("No block found at height 0"), Err(e) => println!("Failed to get block: {}", e), } - + // Get current state match store.get_state().await { Ok(Some(state)) => { @@ -89,7 +97,7 @@ async fn main() -> Result<(), Box> { Ok(None) => println!("No state found"), Err(e) => println!("Failed to get state: {}", e), } - + // Get metadata by key match store.get_metadata("test_key".to_string()).await { Ok(value) => { @@ -97,7 +105,7 @@ async fn main() -> Result<(), Box> { } Err(e) => println!("Failed to get metadata: {}", e), } - + Ok(()) } @@ -106,4 +114,4 @@ mod hex { pub fn encode(bytes: &[u8]) -> String { bytes.iter().map(|b| format!("{:02x}", b)).collect() } -} \ No newline at end of file +} diff --git a/client/crates/rollkit-client/src/client.rs b/client/crates/rollkit-client/src/client.rs index 0d427dece1..70aac60294 100644 --- a/client/crates/rollkit-client/src/client.rs +++ b/client/crates/rollkit-client/src/client.rs @@ -13,10 +13,10 @@ impl RollkitClient { pub async fn connect(endpoint: impl Into) -> Result { let endpoint = endpoint.into(); let channel = Self::create_channel(&endpoint).await?; - + Ok(Self { channel, endpoint }) } - + /// Create a new RollkitClient with custom channel configuration pub async fn connect_with_config(endpoint: impl Into, config: F) -> Result where @@ -25,40 +25,40 @@ impl RollkitClient { let endpoint_str = endpoint.into(); let endpoint = Endpoint::from_shared(endpoint_str.clone()) .map_err(|e| RollkitClientError::InvalidEndpoint(e.to_string()))?; - + let endpoint = config(endpoint); let channel = endpoint .connect() .await .map_err(RollkitClientError::Transport)?; - + Ok(Self { channel, endpoint: endpoint_str, }) } - + /// Get the underlying channel pub fn channel(&self) -> &Channel { &self.channel } - + /// Get the endpoint URL pub fn endpoint(&self) -> &str { &self.endpoint } - + async fn create_channel(endpoint: &str) -> Result { let endpoint = Endpoint::from_shared(endpoint.to_string()) .map_err(|e| RollkitClientError::InvalidEndpoint(e.to_string()))? .timeout(Duration::from_secs(10)) .connect_timeout(Duration::from_secs(5)); - + let channel = endpoint .connect() .await .map_err(RollkitClientError::Transport)?; - + Ok(channel) } -} \ No newline at end of file +} diff --git a/client/crates/rollkit-client/src/error.rs b/client/crates/rollkit-client/src/error.rs index 033f3dce82..b33c684291 100644 --- a/client/crates/rollkit-client/src/error.rs +++ b/client/crates/rollkit-client/src/error.rs @@ -4,18 +4,18 @@ use thiserror::Error; pub enum RollkitClientError { #[error("Transport error: {0}")] Transport(#[from] tonic::transport::Error), - + #[error("RPC error: {0}")] Rpc(#[from] tonic::Status), - + #[error("Connection error: {0}")] Connection(String), - + #[error("Invalid endpoint: {0}")] InvalidEndpoint(String), - + #[error("Timeout error")] Timeout, } -pub type Result = std::result::Result; \ No newline at end of file +pub type Result = std::result::Result; diff --git a/client/crates/rollkit-client/src/health.rs b/client/crates/rollkit-client/src/health.rs index c641166126..7c4d2a10b6 100644 --- a/client/crates/rollkit-client/src/health.rs +++ b/client/crates/rollkit-client/src/health.rs @@ -1,7 +1,6 @@ use crate::{client::RollkitClient, error::Result}; use rollkit_types::v1::{ - health_service_client::HealthServiceClient, - GetHealthResponse, HealthStatus, + health_service_client::HealthServiceClient, GetHealthResponse, HealthStatus, }; use tonic::Request; @@ -15,26 +14,26 @@ impl HealthClient { let inner = HealthServiceClient::new(client.channel().clone()); Self { inner } } - + /// Check if the node is alive and get its health status pub async fn livez(&mut self) -> Result { let request = Request::new(()); let response = self.inner.livez(request).await?; - + Ok(response.into_inner().status()) } - + /// Get the full health response pub async fn get_health(&mut self) -> Result { let request = Request::new(()); let response = self.inner.livez(request).await?; - + Ok(response.into_inner()) } - + /// Check if the node is healthy (status is PASS) pub async fn is_healthy(&mut self) -> Result { let status = self.livez().await?; Ok(status == HealthStatus::Pass) } -} \ No newline at end of file +} diff --git a/client/crates/rollkit-client/src/lib.rs b/client/crates/rollkit-client/src/lib.rs index 7afb05ea92..f074cc0fba 100644 --- a/client/crates/rollkit-client/src/lib.rs +++ b/client/crates/rollkit-client/src/lib.rs @@ -1,12 +1,12 @@ //! Rollkit Rust Client Library -//! +//! //! This library provides a Rust client for interacting with Rollkit nodes via gRPC. -//! +//! //! # Example -//! +//! //! ```no_run //! use rollkit_client::{RollkitClient, HealthClient}; -//! +//! //! #[tokio::main] //! async fn main() -> Result<(), Box> { //! // Connect to a Rollkit node @@ -30,11 +30,11 @@ pub mod store; // Re-export main types for convenience pub use client::RollkitClient; -pub use error::{RollkitClientError, Result}; +pub use error::{Result, RollkitClientError}; pub use health::HealthClient; pub use p2p::P2PClient; pub use signer::SignerClient; pub use store::StoreClient; // Re-export types from rollkit-types for convenience -pub use rollkit_types::v1; \ No newline at end of file +pub use rollkit_types::v1; diff --git a/client/crates/rollkit-client/src/p2p.rs b/client/crates/rollkit-client/src/p2p.rs index 63a91cb5a7..95813788d1 100644 --- a/client/crates/rollkit-client/src/p2p.rs +++ b/client/crates/rollkit-client/src/p2p.rs @@ -1,7 +1,7 @@ use crate::{client::RollkitClient, error::Result}; use rollkit_types::v1::{ - p2p_service_client::P2pServiceClient, - GetNetInfoResponse, GetPeerInfoResponse, NetInfo, PeerInfo, + p2p_service_client::P2pServiceClient, GetNetInfoResponse, GetPeerInfoResponse, NetInfo, + PeerInfo, }; use tonic::Request; @@ -15,42 +15,42 @@ impl P2PClient { let inner = P2pServiceClient::new(client.channel().clone()); Self { inner } } - + /// Get information about connected peers pub async fn get_peer_info(&mut self) -> Result> { let request = Request::new(()); let response = self.inner.get_peer_info(request).await?; - + Ok(response.into_inner().peers) } - + /// Get network information pub async fn get_net_info(&mut self) -> Result { let request = Request::new(()); let response = self.inner.get_net_info(request).await?; - + Ok(response.into_inner().net_info.unwrap_or_default()) } - + /// Get the full peer info response pub async fn get_peer_info_response(&mut self) -> Result { let request = Request::new(()); let response = self.inner.get_peer_info(request).await?; - + Ok(response.into_inner()) } - + /// Get the full network info response pub async fn get_net_info_response(&mut self) -> Result { let request = Request::new(()); let response = self.inner.get_net_info(request).await?; - + Ok(response.into_inner()) } - + /// Get the number of connected peers pub async fn peer_count(&mut self) -> Result { let peers = self.get_peer_info().await?; Ok(peers.len()) } -} \ No newline at end of file +} diff --git a/client/crates/rollkit-client/src/signer.rs b/client/crates/rollkit-client/src/signer.rs index 8231dace13..bb2a31b36d 100644 --- a/client/crates/rollkit-client/src/signer.rs +++ b/client/crates/rollkit-client/src/signer.rs @@ -1,7 +1,7 @@ use crate::{client::RollkitClient, error::Result}; use rollkit_types::v1::{ - signer_service_client::SignerServiceClient, - SignRequest, SignResponse, GetPublicRequest, GetPublicResponse, + signer_service_client::SignerServiceClient, GetPublicRequest, GetPublicResponse, SignRequest, + SignResponse, }; use tonic::Request; @@ -15,36 +15,36 @@ impl SignerClient { let inner = SignerServiceClient::new(client.channel().clone()); Self { inner } } - + /// Sign a message pub async fn sign(&mut self, message: Vec) -> Result> { let request = Request::new(SignRequest { message }); let response = self.inner.sign(request).await?; - + Ok(response.into_inner().signature) } - + /// Get the public key pub async fn get_public_key(&mut self) -> Result> { let request = Request::new(GetPublicRequest {}); let response = self.inner.get_public(request).await?; - + Ok(response.into_inner().public_key) } - + /// Get the full sign response pub async fn sign_full(&mut self, message: Vec) -> Result { let request = Request::new(SignRequest { message }); let response = self.inner.sign(request).await?; - + Ok(response.into_inner()) } - + /// Get the full public key response pub async fn get_public_full(&mut self) -> Result { let request = Request::new(GetPublicRequest {}); let response = self.inner.get_public(request).await?; - + Ok(response.into_inner()) } -} \ No newline at end of file +} diff --git a/client/crates/rollkit-client/src/store.rs b/client/crates/rollkit-client/src/store.rs index dc19650c7a..9c0883d8da 100644 --- a/client/crates/rollkit-client/src/store.rs +++ b/client/crates/rollkit-client/src/store.rs @@ -1,9 +1,7 @@ use crate::{client::RollkitClient, error::Result}; use rollkit_types::v1::{ - store_service_client::StoreServiceClient, - Block, GetBlockRequest, GetBlockResponse, - GetStateResponse, GetMetadataRequest, GetMetadataResponse, - get_block_request::Identifier, + get_block_request::Identifier, store_service_client::StoreServiceClient, Block, + GetBlockRequest, GetBlockResponse, GetMetadataRequest, GetMetadataResponse, GetStateResponse, State, }; use tonic::Request; @@ -18,76 +16,76 @@ impl StoreClient { let inner = StoreServiceClient::new(client.channel().clone()); Self { inner } } - + /// Get a block by height pub async fn get_block_by_height(&mut self, height: u64) -> Result> { let request = Request::new(GetBlockRequest { identifier: Some(Identifier::Height(height)), }); let response = self.inner.get_block(request).await?; - + Ok(response.into_inner().block) } - + /// Get a block by hash pub async fn get_block_by_hash(&mut self, hash: Vec) -> Result> { let request = Request::new(GetBlockRequest { identifier: Some(Identifier::Hash(hash)), }); let response = self.inner.get_block(request).await?; - + Ok(response.into_inner().block) } - + /// Get the current state pub async fn get_state(&mut self) -> Result> { let request = Request::new(()); let response = self.inner.get_state(request).await?; - + Ok(response.into_inner().state) } - + /// Get metadata by key pub async fn get_metadata(&mut self, key: String) -> Result> { let request = Request::new(GetMetadataRequest { key }); let response = self.inner.get_metadata(request).await?; - + Ok(response.into_inner().value) } - + /// Get the full block response by height pub async fn get_block_full_by_height(&mut self, height: u64) -> Result { let request = Request::new(GetBlockRequest { identifier: Some(Identifier::Height(height)), }); let response = self.inner.get_block(request).await?; - + Ok(response.into_inner()) } - + /// Get the full block response by hash pub async fn get_block_full_by_hash(&mut self, hash: Vec) -> Result { let request = Request::new(GetBlockRequest { identifier: Some(Identifier::Hash(hash)), }); let response = self.inner.get_block(request).await?; - + Ok(response.into_inner()) } - + /// Get the full state response pub async fn get_state_full(&mut self) -> Result { let request = Request::new(()); let response = self.inner.get_state(request).await?; - + Ok(response.into_inner()) } - + /// Get the full metadata response pub async fn get_metadata_full(&mut self, key: String) -> Result { let request = Request::new(GetMetadataRequest { key }); let response = self.inner.get_metadata(request).await?; - + Ok(response.into_inner()) } -} \ No newline at end of file +} diff --git a/client/crates/rollkit-client/tests/integration_test.rs b/client/crates/rollkit-client/tests/integration_test.rs index 8fba9b37db..56f00a0345 100644 --- a/client/crates/rollkit-client/tests/integration_test.rs +++ b/client/crates/rollkit-client/tests/integration_test.rs @@ -5,7 +5,7 @@ async fn test_client_creation() { // Test creating a client with an invalid endpoint - will fail during connection let result = RollkitClient::connect("http://localhost:12345").await; assert!(result.is_err()); - + match result.unwrap_err() { RollkitClientError::Transport(_) => {} e => panic!("Expected Transport error, got: {:?}", e), @@ -15,21 +15,19 @@ async fn test_client_creation() { #[tokio::test] async fn test_client_with_config() { use std::time::Duration; - + // Test creating a client with custom configuration - let result = RollkitClient::connect_with_config( - "http://localhost:50051", - |endpoint| { - endpoint - .timeout(Duration::from_secs(5)) - .connect_timeout(Duration::from_secs(2)) - } - ).await; - + let result = RollkitClient::connect_with_config("http://localhost:50051", |endpoint| { + endpoint + .timeout(Duration::from_secs(5)) + .connect_timeout(Duration::from_secs(2)) + }) + .await; + // This will fail to connect since no server is running, but it should be a transport error assert!(result.is_err()); match result.unwrap_err() { RollkitClientError::Transport(_) => {} _ => panic!("Expected Transport error"), } -} \ No newline at end of file +} From 41bc230c21cc63c074468a74fd2bd66ba303c212 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 2 Jul 2025 15:35:53 +0200 Subject: [PATCH 08/16] clippy --- .../crates/rollkit-client/examples/basic.rs | 20 +++++++++---------- .../rollkit-client/tests/integration_test.rs | 2 +- client/crates/rollkit-types/build.rs | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/client/crates/rollkit-client/examples/basic.rs b/client/crates/rollkit-client/examples/basic.rs index f58644dfdf..a06c9d3e8e 100644 --- a/client/crates/rollkit-client/examples/basic.rs +++ b/client/crates/rollkit-client/examples/basic.rs @@ -9,7 +9,7 @@ async fn main() -> Result<(), Box> { // Connect to a Rollkit node let endpoint = std::env::var("ROLLKIT_ENDPOINT").unwrap_or_else(|_| "http://localhost:50051".to_string()); - println!("Connecting to Rollkit node at: {}", endpoint); + println!("Connecting to Rollkit node at: {endpoint}"); let client = RollkitClient::connect(&endpoint).await?; println!("Successfully connected to Rollkit node"); @@ -22,7 +22,7 @@ async fn main() -> Result<(), Box> { println!("Health status: {:?}", health_response.status()); println!("Node is healthy: {}", health.is_healthy().await?); } - Err(e) => println!("Failed to get health status: {}", e), + Err(e) => println!("Failed to get health status: {e}"), } // Get P2P information @@ -34,7 +34,7 @@ async fn main() -> Result<(), Box> { println!("Listen addresses: {:?}", net_info.listen_addresses); println!("Connected peers: {:?}", net_info.connected_peers); } - Err(e) => println!("Failed to get network info: {}", e), + Err(e) => println!("Failed to get network info: {e}"), } match p2p.get_peer_info().await { @@ -44,7 +44,7 @@ async fn main() -> Result<(), Box> { println!(" Peer ID: {}, Address: {}", peer.id, peer.address); } } - Err(e) => println!("Failed to get peer info: {}", e), + Err(e) => println!("Failed to get peer info: {e}"), } // Get signer information @@ -54,7 +54,7 @@ async fn main() -> Result<(), Box> { Ok(pubkey) => { println!("Public key (hex): {}", hex::encode(&pubkey)); } - Err(e) => println!("Failed to get public key: {}", e), + Err(e) => println!("Failed to get public key: {e}"), } // Example: Sign a message @@ -64,7 +64,7 @@ async fn main() -> Result<(), Box> { println!("Message signed successfully"); println!("Signature (hex): {}", hex::encode(&signature)); } - Err(e) => println!("Failed to sign message: {}", e), + Err(e) => println!("Failed to sign message: {e}"), } // Get store information @@ -85,7 +85,7 @@ async fn main() -> Result<(), Box> { ); } Ok(None) => println!("No block found at height 0"), - Err(e) => println!("Failed to get block: {}", e), + Err(e) => println!("Failed to get block: {e}"), } // Get current state @@ -95,7 +95,7 @@ async fn main() -> Result<(), Box> { println!(" Last block height: {}", state.last_block_height); } Ok(None) => println!("No state found"), - Err(e) => println!("Failed to get state: {}", e), + Err(e) => println!("Failed to get state: {e}"), } // Get metadata by key @@ -103,7 +103,7 @@ async fn main() -> Result<(), Box> { Ok(value) => { println!("Metadata value: {}", hex::encode(&value)); } - Err(e) => println!("Failed to get metadata: {}", e), + Err(e) => println!("Failed to get metadata: {e}"), } Ok(()) @@ -112,6 +112,6 @@ async fn main() -> Result<(), Box> { // Helper function to encode bytes as hex (you'll need to add 'hex' to dev-dependencies) mod hex { pub fn encode(bytes: &[u8]) -> String { - bytes.iter().map(|b| format!("{:02x}", b)).collect() + bytes.iter().map(|b| format!("{b:02x}")).collect() } } diff --git a/client/crates/rollkit-client/tests/integration_test.rs b/client/crates/rollkit-client/tests/integration_test.rs index 56f00a0345..6112853839 100644 --- a/client/crates/rollkit-client/tests/integration_test.rs +++ b/client/crates/rollkit-client/tests/integration_test.rs @@ -8,7 +8,7 @@ async fn test_client_creation() { match result.unwrap_err() { RollkitClientError::Transport(_) => {} - e => panic!("Expected Transport error, got: {:?}", e), + e => panic!("Expected Transport error, got: {e:?}"), } } diff --git a/client/crates/rollkit-types/build.rs b/client/crates/rollkit-types/build.rs index 61977f3ab1..44b79a99ae 100644 --- a/client/crates/rollkit-types/build.rs +++ b/client/crates/rollkit-types/build.rs @@ -7,7 +7,7 @@ fn main() -> Result<(), Box> { .into_iter() .filter_map(|entry| { let path = entry.ok()?.path().to_path_buf(); - if path.extension().map_or(false, |ext| ext == "proto") { + if path.extension().is_some_and(|ext| ext == "proto") { Some(path) } else { None From a47f287785dab436d6ccd22088407357453842d5 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 2 Jul 2025 15:49:58 +0200 Subject: [PATCH 09/16] etst --- .github/workflows/rust-proto-check.yml | 14 +++++- client/crates/rollkit-types/.gitattributes | 3 ++ client/crates/rollkit-types/README.md | 58 ++++++++++++++++++++++ client/crates/rollkit-types/build.rs | 5 ++ client/scripts/generate-protos.sh | 39 +++++++++++++++ scripts/proto.mk | 18 +++++++ 6 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 client/crates/rollkit-types/.gitattributes create mode 100644 client/crates/rollkit-types/README.md create mode 100755 client/scripts/generate-protos.sh diff --git a/.github/workflows/rust-proto-check.yml b/.github/workflows/rust-proto-check.yml index 06bda400fc..7d1b453e75 100644 --- a/.github/workflows/rust-proto-check.yml +++ b/.github/workflows/rust-proto-check.yml @@ -54,9 +54,19 @@ jobs: - name: Check for uncommitted changes run: | if ! git diff --exit-code client/crates/rollkit-types/src/proto/; then - echo "::error::Generated proto files are not up to date. Please run 'cargo build' in client/crates/rollkit-types and commit the changes." + echo "::error::Generated proto files are not up to date." + echo "" + echo "This is likely due to protoc version differences." + echo "CI uses protoc version 25.1, your local version may differ." + echo "" + echo "To fix this:" + echo "1. Install protoc version 25.1" + echo "2. Run: ./client/scripts/generate-protos.sh" + echo "3. Commit the changes" + echo "" echo "Differences found:" - git diff client/crates/rollkit-types/src/proto/ + git diff --stat client/crates/rollkit-types/src/proto/ + git diff client/crates/rollkit-types/src/proto/ | head -100 exit 1 fi diff --git a/client/crates/rollkit-types/.gitattributes b/client/crates/rollkit-types/.gitattributes new file mode 100644 index 0000000000..fdd8844eef --- /dev/null +++ b/client/crates/rollkit-types/.gitattributes @@ -0,0 +1,3 @@ +# Ensure consistent line endings for generated files +src/proto/*.rs text eol=lf +*.proto text eol=lf \ No newline at end of file diff --git a/client/crates/rollkit-types/README.md b/client/crates/rollkit-types/README.md new file mode 100644 index 0000000000..2d741dffc4 --- /dev/null +++ b/client/crates/rollkit-types/README.md @@ -0,0 +1,58 @@ +# rollkit-types + +Proto-generated types for Rollkit. + +## Building + +The proto files are automatically generated during the build process: + +```bash +cargo build +``` + +## Proto Generation + +The generated code is committed to the repository. If you modify the proto files, you need to regenerate: + +```bash +# From the repository root +make rust-proto-gen + +# Or directly +cd client/crates/rollkit-types +cargo build +``` + +## Version Consistency + +**Important**: The CI uses protoc version 25.1. If your local protoc version differs, you may see formatting differences in the generated files. + +To check your protoc version: +```bash +protoc --version +``` + +To ensure consistency with CI: +1. Install protoc version 25.1 +2. Use the provided script: `./client/scripts/generate-protos.sh` +3. Or use the Makefile: `make rust-proto-gen` + +### Common Issues + +If you see differences in generated files between local and CI: +- It's usually due to protoc version differences +- Different versions may format the generated code slightly differently +- The functionality remains the same, only formatting changes + +To avoid this: +- Use the same protoc version as CI (25.1) +- Or accept the formatting from your version and update CI if needed + +## Dependencies + +This crate requires: +- `protoc` (Protocol Buffers compiler) +- `tonic-build` for code generation +- `prost` for runtime support + +The build dependencies are specified in `Cargo.toml` and use workspace versions for consistency. \ No newline at end of file diff --git a/client/crates/rollkit-types/build.rs b/client/crates/rollkit-types/build.rs index 44b79a99ae..1f05cdc63b 100644 --- a/client/crates/rollkit-types/build.rs +++ b/client/crates/rollkit-types/build.rs @@ -19,7 +19,12 @@ fn main() -> Result<(), Box> { .build_server(true) .build_client(true) .out_dir("src/proto") + // Ensure consistent formatting across different protoc versions + .protoc_arg("--experimental_allow_proto3_optional") .compile(&proto_files, &["../../../proto"])?; + + // Add a note about the protoc version used + println!("cargo:warning=Proto files compiled with protoc. For consistent results, use protoc version 25.x"); Ok(()) } diff --git a/client/scripts/generate-protos.sh b/client/scripts/generate-protos.sh new file mode 100755 index 0000000000..d306ad6823 --- /dev/null +++ b/client/scripts/generate-protos.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -euo pipefail + +# Script to generate proto files with the same version as CI +# This ensures consistent output between local development and CI + +PROTOC_VERSION="25.1" +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PROJECT_ROOT="$( cd "$SCRIPT_DIR/../.." && pwd )" + +echo "Checking protoc version..." +CURRENT_VERSION=$(protoc --version | cut -d' ' -f2) + +if [ "$CURRENT_VERSION" != "$PROTOC_VERSION" ]; then + echo "Warning: Your protoc version ($CURRENT_VERSION) differs from CI version ($PROTOC_VERSION)" + echo "This may cause differences in generated files." + echo "" + echo "To install the correct version:" + echo " - macOS: brew install protobuf@$PROTOC_VERSION" + echo " - Linux: Download from https://github.com/protocolbuffers/protobuf/releases/tag/v$PROTOC_VERSION" + echo "" + read -p "Continue anyway? (y/n) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +echo "Cleaning existing generated files..." +rm -f "$PROJECT_ROOT/client/crates/rollkit-types/src/proto/"*.rs + +echo "Generating proto files..." +cd "$PROJECT_ROOT/client/crates/rollkit-types" +cargo build + +echo "Proto generation complete!" +echo "" +echo "If you see differences in git, it may be due to protoc version differences." +echo "CI uses protoc version $PROTOC_VERSION" \ No newline at end of file diff --git a/scripts/proto.mk b/scripts/proto.mk index 7b45158a65..3004bd13d2 100644 --- a/scripts/proto.mk +++ b/scripts/proto.mk @@ -12,3 +12,21 @@ proto-lint: @echo "--> Linting Protobuf files" @$(DOCKER_BUF) lint --error-format=json .PHONY: proto-lint + +## rust-proto-gen: Generate Rust protobuf files +rust-proto-gen: + @echo "--> Generating Rust protobuf files" + @cd client/crates/rollkit-types && cargo build +.PHONY: rust-proto-gen + +## rust-proto-check: Check if Rust protobuf files are up to date +rust-proto-check: + @echo "--> Checking Rust protobuf files" + @rm -rf client/crates/rollkit-types/src/proto/*.rs + @cd client/crates/rollkit-types && cargo build + @if ! git diff --exit-code client/crates/rollkit-types/src/proto/; then \ + echo "Error: Generated Rust proto files are not up to date."; \ + echo "Run 'make rust-proto-gen' and commit the changes."; \ + exit 1; \ + fi +.PHONY: rust-proto-check From c1105fcce479877329ed4ae6b3c77e2ca34dd695 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 2 Jul 2025 15:52:49 +0200 Subject: [PATCH 10/16] remove rust code from test coverage --- codecov.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/codecov.yml b/codecov.yml index 74d7c22ea7..277b230a38 100644 --- a/codecov.yml +++ b/codecov.yml @@ -16,3 +16,4 @@ ignore: - "da/cmd" - "execution/evm" # EVM is covered in e2e/integration tests - "**/metrics.go" + - "client" # TODO: add more tests From 00d9da854362bd2635aea8fb076b9b51de7564ab Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 3 Jul 2025 13:19:57 +0200 Subject: [PATCH 11/16] use manifest --- client/crates/rollkit-types/build.rs | 30 +++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/client/crates/rollkit-types/build.rs b/client/crates/rollkit-types/build.rs index 1f05cdc63b..f35ab11576 100644 --- a/client/crates/rollkit-types/build.rs +++ b/client/crates/rollkit-types/build.rs @@ -1,17 +1,18 @@ -use std::path::PathBuf; +use std::{env, path::Path}; use walkdir::WalkDir; -// Collect all .proto files recursively under /proto/ and compile. fn main() -> Result<(), Box> { - let proto_files: Vec = WalkDir::new("../../../proto") + let manifest_dir_str = env::var("CARGO_MANIFEST_DIR")?; + let manifest_dir = Path::new(&manifest_dir_str); + // Make the include dir absolute and resolved (no "..", symlinks, etc.) + let proto_root = manifest_dir.join("../../../proto").canonicalize()?; + + // Collect the .proto files + let proto_files: Vec<_> = WalkDir::new(&proto_root) .into_iter() - .filter_map(|entry| { - let path = entry.ok()?.path().to_path_buf(); - if path.extension().is_some_and(|ext| ext == "proto") { - Some(path) - } else { - None - } + .filter_map(|e| { + let p = e.ok()?.into_path(); + (p.extension()?.to_str()? == "proto").then_some(p) }) .collect(); @@ -19,12 +20,9 @@ fn main() -> Result<(), Box> { .build_server(true) .build_client(true) .out_dir("src/proto") - // Ensure consistent formatting across different protoc versions - .protoc_arg("--experimental_allow_proto3_optional") - .compile(&proto_files, &["../../../proto"])?; - - // Add a note about the protoc version used - println!("cargo:warning=Proto files compiled with protoc. For consistent results, use protoc version 25.x"); + // pass the absolute include dir + .compile(&proto_files, &[proto_root.as_path()])?; + println!("cargo:rerun-if-changed={}", proto_root.display()); Ok(()) } From 9a81dff88d5e070caa88892d3b296d9ef791b393 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 3 Jul 2025 14:53:00 +0200 Subject: [PATCH 12/16] fix yamllint --- .github/actions/rust-setup/action.yml | 20 ++++++++++---------- .github/workflows/rust-ci-status.yml | 6 ++++-- .github/workflows/rust-proto-check.yml | 2 ++ .github/workflows/rust-publish.yml | 2 +- .github/workflows/rust-test.yml | 4 +++- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/.github/actions/rust-setup/action.yml b/.github/actions/rust-setup/action.yml index 29f734e0d7..70c5b1f942 100644 --- a/.github/actions/rust-setup/action.yml +++ b/.github/actions/rust-setup/action.yml @@ -1,21 +1,21 @@ -name: 'Setup Rust' -description: 'Setup Rust toolchain with caching and protoc' +name: "Setup Rust" +description: "Setup Rust toolchain with caching and protoc" inputs: toolchain: - description: 'Rust toolchain to install' + description: "Rust toolchain to install" required: false - default: 'stable' + default: "stable" components: - description: 'Rust components to install' + description: "Rust components to install" required: false - default: '' + default: "" cache-key: - description: 'Additional cache key for dependencies' + description: "Additional cache key for dependencies" required: false - default: 'default' + default: "default" runs: - using: 'composite' + using: "composite" steps: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master @@ -48,4 +48,4 @@ runs: run: | rustc --version cargo --version - protoc --version \ No newline at end of file + protoc --version diff --git a/.github/workflows/rust-ci-status.yml b/.github/workflows/rust-ci-status.yml index 60eab8185f..8f03a0daf0 100644 --- a/.github/workflows/rust-ci-status.yml +++ b/.github/workflows/rust-ci-status.yml @@ -10,6 +10,8 @@ jobs: status: name: Update CI Status runs-on: ubuntu-latest + permissions: + contents: read if: github.event.workflow_run.conclusion != 'skipped' steps: - name: Report status @@ -17,8 +19,8 @@ jobs: echo "Workflow: ${{ github.event.workflow_run.name }}" echo "Status: ${{ github.event.workflow_run.conclusion }}" echo "Branch: ${{ github.event.workflow_run.head_branch }}" - + if [ "${{ github.event.workflow_run.conclusion }}" != "success" ]; then echo "::error::Rust CI workflow failed" exit 1 - fi \ No newline at end of file + fi diff --git a/.github/workflows/rust-proto-check.yml b/.github/workflows/rust-proto-check.yml index 7d1b453e75..05a59199c9 100644 --- a/.github/workflows/rust-proto-check.yml +++ b/.github/workflows/rust-proto-check.yml @@ -11,6 +11,8 @@ on: branches: - main - release/* +permissions: + contents: read jobs: check-proto-generation: diff --git a/.github/workflows/rust-publish.yml b/.github/workflows/rust-publish.yml index b0ef39fcc9..6752263844 100644 --- a/.github/workflows/rust-publish.yml +++ b/.github/workflows/rust-publish.yml @@ -95,4 +95,4 @@ jobs: See the [README](https://github.com/rollkit/rollkit/tree/main/client/crates/rollkit-client) for usage examples. draft: false - prerelease: false \ No newline at end of file + prerelease: false diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 74d808dcdf..09b7885a0e 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -1,4 +1,6 @@ name: Rust Tests +permissions: + contents: read on: pull_request: @@ -85,4 +87,4 @@ jobs: files: lcov.info flags: rust fail_ci_if_error: false - token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file + token: ${{ secrets.CODECOV_TOKEN }} From fb4b9a8510acc81cf8eafb2de59b5608e4edddee Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 3 Jul 2025 16:13:36 +0200 Subject: [PATCH 13/16] markdownlint --- client/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/README.md b/client/README.md index d66492ac77..7e6e282b83 100644 --- a/client/README.md +++ b/client/README.md @@ -4,7 +4,7 @@ This directory contains client libraries for interacting with Rollkit nodes in v ## Structure -``` +```ascii client/ ├── crates/ # Rust client libraries │ ├── rollkit-types/ # Generated protobuf types for Rust @@ -23,6 +23,7 @@ Contains all the protobuf-generated types and service definitions. This crate is ### rollkit-client A high-level client library that provides: + - Easy-to-use wrappers around the gRPC services - Connection management with configurable timeouts - Type-safe interfaces @@ -39,4 +40,4 @@ This directory is structured to support additional client libraries in the futur - Python client - Go client -Each language will have its own subdirectory with generated types and high-level client implementations. \ No newline at end of file +Each language will have its own subdirectory with generated types and high-level client implementations. From 59b192ad65b4f497fc37baf4cc1739960d3a3f3c Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 3 Jul 2025 16:17:04 +0200 Subject: [PATCH 14/16] fix build --- .github/workflows/rust-proto-check.yml | 107 ------------------------- scripts/proto.mk | 1 + 2 files changed, 1 insertion(+), 107 deletions(-) delete mode 100644 .github/workflows/rust-proto-check.yml diff --git a/.github/workflows/rust-proto-check.yml b/.github/workflows/rust-proto-check.yml deleted file mode 100644 index 05a59199c9..0000000000 --- a/.github/workflows/rust-proto-check.yml +++ /dev/null @@ -1,107 +0,0 @@ -name: Rust Proto Generation Check - -on: - pull_request: - paths: - - "proto/**" - - "client/crates/rollkit-types/build.rs" - - "client/crates/rollkit-types/src/proto/**" - - ".github/workflows/rust-proto-check.yml" - push: - branches: - - main - - release/* -permissions: - contents: read - -jobs: - check-proto-generation: - name: Check Proto Generation - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - - - name: Install protoc - uses: arduino/setup-protoc@v3 - with: - version: "25.1" - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Cache Rust dependencies - uses: actions/cache@v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-cargo-proto-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-proto- - - - name: Remove existing generated files - run: | - rm -rf client/crates/rollkit-types/src/proto/*.rs - - - name: Generate proto files - run: | - cd client/crates/rollkit-types - cargo build - - - name: Check for uncommitted changes - run: | - if ! git diff --exit-code client/crates/rollkit-types/src/proto/; then - echo "::error::Generated proto files are not up to date." - echo "" - echo "This is likely due to protoc version differences." - echo "CI uses protoc version 25.1, your local version may differ." - echo "" - echo "To fix this:" - echo "1. Install protoc version 25.1" - echo "2. Run: ./client/scripts/generate-protos.sh" - echo "3. Commit the changes" - echo "" - echo "Differences found:" - git diff --stat client/crates/rollkit-types/src/proto/ - git diff client/crates/rollkit-types/src/proto/ | head -100 - exit 1 - fi - - proto-breaking-changes: - name: Check Proto Breaking Changes - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install buf - uses: bufbuild/buf-setup-action@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - - - name: Check for breaking changes - run: | - # Create buf.yaml if it doesn't exist - if [ ! -f buf.yaml ]; then - cat > buf.yaml << EOF - version: v1 - breaking: - use: - - FILE - lint: - use: - - DEFAULT - EOF - fi - - # Check for breaking changes against main branch - git fetch origin main - buf breaking proto --against .git#branch=origin/main,subdir=proto || echo "::warning::Breaking changes detected in proto files" diff --git a/scripts/proto.mk b/scripts/proto.mk index 3004bd13d2..a878d2e53a 100644 --- a/scripts/proto.mk +++ b/scripts/proto.mk @@ -5,6 +5,7 @@ DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bu proto-gen: @echo "--> Generating Protobuf files" buf generate --path="./proto/rollkit" --template="buf.gen.yaml" --config="buf.yaml" + cargo build .PHONY: proto-gen ## proto-lint: Lint protobuf files. Requires docker. From 4da823b202d819211ced8bc2038ef0f775c29392 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 3 Jul 2025 16:24:17 +0200 Subject: [PATCH 15/16] markdownlint --- client/crates/rollkit-client/README.md | 13 ++++++++++--- client/crates/rollkit-types/README.md | 7 ++++++- scripts/README-EVM.md | 2 ++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/client/crates/rollkit-client/README.md b/client/crates/rollkit-client/README.md index 33d415e859..7b150180a7 100644 --- a/client/crates/rollkit-client/README.md +++ b/client/crates/rollkit-client/README.md @@ -2,8 +2,10 @@ [![Rust Tests](https://github.com/rollkit/rollkit/actions/workflows/rust-test.yml/badge.svg)](https://github.com/rollkit/rollkit/actions/workflows/rust-test.yml) [![Rust Lint](https://github.com/rollkit/rollkit/actions/workflows/rust-lint.yml/badge.svg)](https://github.com/rollkit/rollkit/actions/workflows/rust-lint.yml) + [![crates.io](https://img.shields.io/crates/v/rollkit-client.svg)](https://crates.io/crates/rollkit-client) [![docs.rs](https://docs.rs/rollkit-client/badge.svg)](https://docs.rs/rollkit-client) + A Rust client library for interacting with Rollkit nodes via gRPC. @@ -36,12 +38,12 @@ use rollkit_client::{RollkitClient, HealthClient}; async fn main() -> Result<(), Box> { // Connect to a Rollkit node let client = RollkitClient::connect("http://localhost:50051").await?; - + // Check health let mut health = HealthClient::new(&client); let is_healthy = health.is_healthy().await?; println!("Node healthy: {}", is_healthy); - + Ok(()) } ``` @@ -68,18 +70,22 @@ let client = RollkitClient::connect_with_config( The client provides wrappers for all Rollkit gRPC services: ### Health Service + - `livez()` - Check if the node is alive - `is_healthy()` - Check if the node is healthy ### P2P Service + - `get_peer_info()` - Get information about connected peers - `get_net_info()` - Get network information ### Signer Service + - `sign(message)` - Sign a message - `get_public_key()` - Get the node's public key ### Store Service + - `get_block(height)` - Get a block by height - `get_state(height)` - Get state at a specific height - `get_metadata(initial_height, latest_height)` - Get metadata for a height range @@ -95,6 +101,7 @@ cargo run --example basic ## Error Handling All methods return `Result` where `RollkitClientError` encompasses: + - Transport errors - RPC errors - Connection errors @@ -103,4 +110,4 @@ All methods return `Result` where `RollkitClientError` en ## License -Apache-2.0 \ No newline at end of file +Apache-2.0 diff --git a/client/crates/rollkit-types/README.md b/client/crates/rollkit-types/README.md index 2d741dffc4..08eaba8386 100644 --- a/client/crates/rollkit-types/README.md +++ b/client/crates/rollkit-types/README.md @@ -28,11 +28,13 @@ cargo build **Important**: The CI uses protoc version 25.1. If your local protoc version differs, you may see formatting differences in the generated files. To check your protoc version: + ```bash protoc --version ``` To ensure consistency with CI: + 1. Install protoc version 25.1 2. Use the provided script: `./client/scripts/generate-protos.sh` 3. Or use the Makefile: `make rust-proto-gen` @@ -40,19 +42,22 @@ To ensure consistency with CI: ### Common Issues If you see differences in generated files between local and CI: + - It's usually due to protoc version differences - Different versions may format the generated code slightly differently - The functionality remains the same, only formatting changes To avoid this: + - Use the same protoc version as CI (25.1) - Or accept the formatting from your version and update CI if needed ## Dependencies This crate requires: + - `protoc` (Protocol Buffers compiler) - `tonic-build` for code generation - `prost` for runtime support -The build dependencies are specified in `Cargo.toml` and use workspace versions for consistency. \ No newline at end of file +The build dependencies are specified in `Cargo.toml` and use workspace versions for consistency. diff --git a/scripts/README-EVM.md b/scripts/README-EVM.md index 2710380867..4792e8916e 100644 --- a/scripts/README-EVM.md +++ b/scripts/README-EVM.md @@ -50,6 +50,7 @@ go build -tags run_evm -o run-evm-nodes scripts/run-evm-nodes.go - Full Node EVM: ports 8555 (RPC), 8561 (Engine), 8556 (WS) 3. **Rollkit Nodes**: + - Initializes and starts the sequencer node: - RPC: - P2P: 127.0.0.1:7676 @@ -57,6 +58,7 @@ go build -tags run_evm -o run-evm-nodes scripts/run-evm-nodes.go - RPC: - P2P: 127.0.0.1:7677 - Automatically connects to sequencer via P2P + 4. **Monitoring**: - Monitors all processes for unexpected exits From aeb1794261156abab0da1969c0b81080e62de39b Mon Sep 17 00:00:00 2001 From: Marko Date: Thu, 3 Jul 2025 18:39:29 +0200 Subject: [PATCH 16/16] Potential fix for code scanning alert no. 71: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/rust-lint.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/rust-lint.yml b/.github/workflows/rust-lint.yml index 68de402c28..3c4d60e452 100644 --- a/.github/workflows/rust-lint.yml +++ b/.github/workflows/rust-lint.yml @@ -32,6 +32,8 @@ jobs: clippy: name: Clippy runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout code uses: actions/checkout@v4