diff --git a/Cargo.lock b/Cargo.lock index 9f365bd..f0478fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -146,6 +146,18 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "argon2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash", +] + [[package]] name = "arraydeque" version = "0.5.1" @@ -164,29 +176,13 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "asn1-rs" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" -dependencies = [ - "asn1-rs-derive 0.5.1", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - [[package]] name = "asn1-rs" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" dependencies = [ - "asn1-rs-derive 0.6.0", + "asn1-rs-derive", "asn1-rs-impl", "displaydoc", "nom", @@ -196,18 +192,6 @@ dependencies = [ "time", ] -[[package]] -name = "asn1-rs-derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", - "synstructure", -] - [[package]] name = "asn1-rs-derive" version = "0.6.0" @@ -216,7 +200,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "synstructure", ] @@ -228,7 +212,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -268,29 +252,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", -] - -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -301,7 +263,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -373,40 +335,13 @@ dependencies = [ "fs_extra", ] -[[package]] -name = "axum" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" -dependencies = [ - "async-trait", - "axum-core 0.4.5", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "itoa", - "matchit 0.7.3", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper", - "tower 0.5.2", - "tower-layer", - "tower-service", -] - [[package]] name = "axum" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ - "axum-core 0.5.2", + "axum-core", "bytes", "form_urlencoded", "futures-util", @@ -416,7 +351,7 @@ dependencies = [ "hyper", "hyper-util", "itoa", - "matchit 0.8.4", + "matchit", "memchr", "mime", "percent-encoding", @@ -428,32 +363,12 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tower 0.5.2", + "tower", "tower-layer", "tower-service", "tracing", ] -[[package]] -name = "axum-core" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.5.2" @@ -583,7 +498,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.104", + "syn", "which", ] @@ -661,6 +576,29 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "bytecheck" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0caa33a2c0edca0419d15ac723dff03f1956f7978329b1e3b5fdaaaed9d3ca8b" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "rancor", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bytemuck" version = "1.23.1" @@ -795,7 +733,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -994,7 +932,7 @@ dependencies = [ "proc-macro2", "quote", "strict", - "syn 2.0.104", + "syn", ] [[package]] @@ -1130,7 +1068,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1170,7 +1108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 2.0.104", + "syn", ] [[package]] @@ -1192,27 +1130,13 @@ dependencies = [ "zeroize", ] -[[package]] -name = "der-parser" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" -dependencies = [ - "asn1-rs 0.6.2", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - [[package]] name = "der-parser" version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ - "asn1-rs 0.7.1", + "asn1-rs", "displaydoc", "nom", "num-bigint", @@ -1247,7 +1171,7 @@ dependencies = [ "convert_case 0.7.1", "proc-macro2", "quote", - "syn 2.0.104", + "syn", "unicode-xid", ] @@ -1291,7 +1215,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1346,7 +1270,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1409,7 +1333,27 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn", +] + +[[package]] +name = "env_filter" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +dependencies = [ + "env_filter", + "log", ] [[package]] @@ -1633,7 +1577,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1734,6 +1678,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core 0.10.0", + "wasip2", + "wasip3", +] + [[package]] name = "gimli" version = "0.31.1" @@ -1748,9 +1706,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "gnort" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1033ebf8ca0e0a249d8996a5979dcfd276d43b2818cb6045993a844250c49516" +checksum = "aef3660ec7d99e31b3d5481d5c2ea525934a38b18ca4d5a64bf53292cf9f1446" dependencies = [ "dashmap", "derive_more", @@ -1760,7 +1718,6 @@ dependencies = [ "nonzero_ext", "once_cell", "thiserror 2.0.12", - "tracing", ] [[package]] @@ -1798,19 +1755,13 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.10.0", + "indexmap", "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.14.5" @@ -1828,6 +1779,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + [[package]] name = "hashlink" version = "0.10.0" @@ -1870,6 +1827,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" + [[package]] name = "hickory-proto" version = "0.25.0-alpha.5" @@ -2098,11 +2061,11 @@ dependencies = [ [[package]] name = "ibig" version = "0.3.6" -source = "git+https://github.com/swpsco/nockchain.git?rev=2b912bff818ac5081109f374e58c5db277b4bb04#2b912bff818ac5081109f374e58c5db277b4bb04" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" dependencies = [ "cfg-if", "num-traits", - "rand 0.8.5", + "rand 0.9.2", "static_assertions", ] @@ -2192,6 +2155,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "idna" version = "1.0.3" @@ -2267,16 +2236,6 @@ dependencies = [ "xmltree", ] -[[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" @@ -2285,6 +2244,7 @@ checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown 0.15.4", + "serde", ] [[package]] @@ -2512,7 +2472,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.104", + "syn", ] [[package]] @@ -2527,6 +2487,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" version = "0.2.174" @@ -2840,7 +2806,7 @@ source = "git+https://github.com/libp2p/rust-libp2p.git?rev=da0017ee887a868e231e dependencies = [ "heck", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -2867,7 +2833,7 @@ dependencies = [ "futures-rustls", "libp2p-core", "libp2p-identity", - "rcgen", + "rcgen 0.13.2", "ring", "rustls", "rustls-webpki", @@ -2984,12 +2950,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "matchit" version = "0.8.4" @@ -3157,10 +3117,30 @@ dependencies = [ "unsigned-varint", ] +[[package]] +name = "munge" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "murmur3" version = "0.5.2" -source = "git+https://github.com/swpsco/nockchain.git?rev=2b912bff818ac5081109f374e58c5db277b4bb04#2b912bff818ac5081109f374e58c5db277b4bb04" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" [[package]] name = "netlink-packet-core" @@ -3246,11 +3226,11 @@ checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" [[package]] name = "nockapp" version = "0.1.0" -source = "git+https://github.com/swpsco/nockchain.git?rev=2b912bff818ac5081109f374e58c5db277b4bb04#2b912bff818ac5081109f374e58c5db277b4bb04" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" dependencies = [ "anyhow", "async-trait", - "axum 0.8.4", + "axum", "axum-server", "bincode 2.0.1", "bitvec", @@ -3263,18 +3243,19 @@ dependencies = [ "dirs", "either", "futures", - "getrandom 0.2.16", + "getrandom 0.3.3", "gnort", "ibig", "instant-acme", "intmap", "nockvm", "nockvm_macros", + "noun-serde", "opentelemetry", "opentelemetry-otlp", "opentelemetry_sdk", - "rand 0.8.5", - "rcgen", + "rand 0.9.2", + "rcgen 0.14.7", "rustls", "rustls-pemfile", "serde", @@ -3287,25 +3268,27 @@ dependencies = [ "tokio", "tokio-rustls", "tokio-util", - "tonic", + "tonic 0.14.3", "tower-http", "tracing", "tracing-opentelemetry", "tracing-subscriber", "tracing-test", - "webpki-roots 0.26.11", - "x509-parser 0.16.0", + "tracing-tracy", + "webpki-roots", + "x509-parser 0.17.0", "yaque", ] [[package]] name = "nockchain-libp2p-io" version = "0.1.0" -source = "git+https://github.com/swpsco/nockchain.git?rev=2b912bff818ac5081109f374e58c5db277b4bb04#2b912bff818ac5081109f374e58c5db277b4bb04" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" dependencies = [ "bs58", "bytes", "config", + "dashmap", "either", "equix", "futures", @@ -3317,21 +3300,49 @@ dependencies = [ "nockapp", "nockvm", "nockvm_macros", - "rand 0.8.5", + "noun-serde", + "rand 0.9.2", "serde", "serde_bytes", "tokio", "tracing", "void", + "zkvm-jetpack", +] + +[[package]] +name = "nockchain-math" +version = "0.1.0" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" +dependencies = [ + "argon2", + "arrayref", + "bs58", + "bytes", + "either", + "hex-literal", + "ibig", + "nockvm", + "nockvm_macros", + "noun-serde", + "num-traits", + "once_cell", + "quickcheck", + "rkyv", + "serde", + "thiserror 2.0.12", + "tracing", ] [[package]] name = "nockvm" version = "0.1.0" -source = "git+https://github.com/swpsco/nockchain.git?rev=2b912bff818ac5081109f374e58c5db277b4bb04#2b912bff818ac5081109f374e58c5db277b4bb04" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" dependencies = [ "autotools", + "bincode 2.0.1", "bitvec", + "bytes", "cc", "either", "ibig", @@ -3345,18 +3356,20 @@ dependencies = [ "nockvm_macros", "num-derive", "num-traits", - "rand 0.8.5", + "rand 0.9.2", + "serde", "signal-hook", "slotmap", "static_assertions", "thiserror 2.0.12", "tracing", + "tracing-core", ] [[package]] name = "nockvm_crypto" version = "0.1.0" -source = "git+https://github.com/swpsco/nockchain.git?rev=2b912bff818ac5081109f374e58c5db277b4bb04#2b912bff818ac5081109f374e58c5db277b4bb04" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" dependencies = [ "aes", "aes-siv", @@ -3371,10 +3384,10 @@ dependencies = [ [[package]] name = "nockvm_macros" version = "0.1.0" -source = "git+https://github.com/swpsco/nockchain.git?rev=2b912bff818ac5081109f374e58c5db277b4bb04#2b912bff818ac5081109f374e58c5db277b4bb04" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" dependencies = [ "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -3411,6 +3424,31 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "noun-serde" +version = "0.1.0" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" +dependencies = [ + "bytes", + "ibig", + "nockvm", + "noun-serde-derive", + "thiserror 2.0.12", + "tracing", +] + +[[package]] +name = "noun-serde-derive" +version = "0.1.0" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" +dependencies = [ + "nockvm", + "proc-macro2", + "quote", + "syn", + "tracing", +] + [[package]] name = "ntapi" version = "0.4.1" @@ -3454,7 +3492,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3494,22 +3532,13 @@ dependencies = [ "memchr", ] -[[package]] -name = "oid-registry" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" -dependencies = [ - "asn1-rs 0.6.2", -] - [[package]] name = "oid-registry" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" dependencies = [ - "asn1-rs 0.7.1", + "asn1-rs", ] [[package]] @@ -3532,23 +3561,23 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "opentelemetry" -version = "0.27.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab70038c28ed37b97d8ed414b6429d343a8bbf44c9f79ec854f3a643029ba6d7" +checksum = "aaf416e4cb72756655126f7dd7bb0af49c674f4c1b9903e80c009e0c37e552e6" dependencies = [ "futures-core", "futures-sink", "js-sys", "pin-project-lite", - "thiserror 1.0.69", + "thiserror 2.0.12", "tracing", ] [[package]] name = "opentelemetry-http" -version = "0.27.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a8a7f5f6ba7c1b286c2fbca0454eaba116f63bbe69ed250b642d36fbb04d80" +checksum = "50f6639e842a97dbea8886e3439710ae463120091e2e064518ba8e716e6ac36d" dependencies = [ "async-trait", "bytes", @@ -3559,12 +3588,10 @@ dependencies = [ [[package]] name = "opentelemetry-otlp" -version = "0.27.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76" +checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b" dependencies = [ - "async-trait", - "futures-core", "http", "opentelemetry", "opentelemetry-http", @@ -3572,43 +3599,40 @@ dependencies = [ "opentelemetry_sdk", "prost", "reqwest", - "thiserror 1.0.69", + "thiserror 2.0.12", "tokio", - "tonic", + "tonic 0.13.1", "tracing", ] [[package]] name = "opentelemetry-proto" -version = "0.27.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e05acbfada5ec79023c85368af14abd0b307c015e9064d249b2a950ef459a6" +checksum = "2e046fd7660710fe5a05e8748e70d9058dc15c94ba914e7c4faa7c728f0e8ddc" dependencies = [ "opentelemetry", "opentelemetry_sdk", "prost", - "tonic", + "tonic 0.13.1", ] [[package]] name = "opentelemetry_sdk" -version = "0.27.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8" +checksum = "11f644aa9e5e31d11896e024305d7e3c98a88884d9f8919dbf37a9991bc47a4b" dependencies = [ - "async-trait", "futures-channel", "futures-executor", "futures-util", - "glob", "opentelemetry", "percent-encoding", - "rand 0.8.5", + "rand 0.9.2", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.12", "tokio", "tokio-stream", - "tracing", ] [[package]] @@ -3662,6 +3686,17 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" @@ -3721,7 +3756,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3751,7 +3786,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3827,7 +3862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", - "syn 2.0.104", + "syn", ] [[package]] @@ -3849,7 +3884,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3881,7 +3916,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3904,7 +3939,27 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn", +] + +[[package]] +name = "ptr_meta" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3943,6 +3998,17 @@ dependencies = [ "unsigned-varint", ] +[[package]] +name = "quickcheck" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95c589f335db0f6aaa168a7cd27b1fc6920f5e1470c804f814d9cd6e62a0f70b" +dependencies = [ + "env_logger", + "log", + "rand 0.10.0", +] + [[package]] name = "quinn" version = "0.11.8" @@ -4040,6 +4106,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rancor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee" +dependencies = [ + "ptr_meta", +] + [[package]] name = "rand" version = "0.8.5" @@ -4061,6 +4136,16 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "getrandom 0.4.1", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -4099,6 +4184,12 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + [[package]] name = "raw-cpuid" version = "11.5.0" @@ -4141,6 +4232,20 @@ dependencies = [ "yasna", ] +[[package]] +name = "rcgen" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "x509-parser 0.18.1", + "yasna", +] + [[package]] name = "redox_syscall" version = "0.5.15" @@ -4205,6 +4310,15 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rend" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" version = "0.12.22" @@ -4230,7 +4344,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tower 0.5.2", + "tower", "tower-http", "tower-service", "url", @@ -4268,6 +4382,36 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a30e631b7f4a03dee9056b8ef6982e8ba371dd5bedb74d3ec86df4499132c70" +dependencies = [ + "bytecheck", + "bytes", + "hashbrown 0.16.1", + "indexmap", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8100bb34c0a1d0f907143db3149e6b4eea3c33b9ee8b189720168e818303986f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ron" version = "0.8.1" @@ -4572,7 +4716,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -4706,6 +4850,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.1" @@ -4797,22 +4947,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "subtle" -version = "2.6.1" +name = "strum" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] [[package]] -name = "syn" -version = "1.0.109" +name = "strum_macros" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ + "heck", "proc-macro2", "quote", - "unicode-ident", + "syn", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.104" @@ -4841,7 +5001,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -4920,9 +5080,9 @@ dependencies = [ [[package]] name = "termimad" -version = "0.31.3" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7301d9c2c4939c97f25376b70d3c13311f8fefdee44092fc361d2a98adc2cbb6" +checksum = "b23646cdde4c2e9d6f2621424751b48653e5755f50163b2ff5ce3b32ebf17104" dependencies = [ "coolor", "crokey", @@ -4960,7 +5120,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -4971,7 +5131,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5065,6 +5225,7 @@ dependencies = [ "slab", "socket2 0.5.10", "tokio-macros", + "tracing", "windows-sys 0.52.0", ] @@ -5076,7 +5237,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5148,16 +5309,13 @@ dependencies = [ [[package]] name = "tonic" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" dependencies = [ - "async-stream", "async-trait", - "axum 0.7.9", "base64 0.22.1", "bytes", - "h2", "http", "http-body", "http-body-util", @@ -5167,33 +5325,43 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "socket2 0.5.10", "tokio", "tokio-stream", - "tower 0.4.13", + "tower", "tower-layer", "tower-service", "tracing", ] [[package]] -name = "tower" -version = "0.4.13" +name = "tonic" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "a286e33f82f8a1ee2df63f4fa35c0becf4a85a0cb03091a15fd7bf0b402dc94a" dependencies = [ - "futures-core", - "futures-util", - "indexmap 1.9.3", + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", "pin-project", - "pin-project-lite", - "rand 0.8.5", - "slab", + "socket2 0.6.0", + "sync_wrapper", "tokio", - "tokio-util", + "tokio-rustls", + "tokio-stream", + "tower", "tower-layer", "tower-service", "tracing", + "webpki-roots", ] [[package]] @@ -5204,9 +5372,12 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", + "indexmap", "pin-project-lite", + "slab", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -5234,7 +5405,7 @@ dependencies = [ "pin-project-lite", "tokio", "tokio-util", - "tower 0.5.2", + "tower", "tower-layer", "tower-service", "tracing", @@ -5272,7 +5443,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5298,9 +5469,9 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.28.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a971f6058498b5c0f1affa23e7ea202057a7301dbff68e968b2d578bcbd053" +checksum = "ddcf5959f39507d0d04d6413119c04f33b623f4f951ebcbdddddfad2d0623a9c" dependencies = [ "js-sys", "once_cell", @@ -5350,7 +5521,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.104", + "syn", +] + +[[package]] +name = "tracing-tracy" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracy-client", +] + +[[package]] +name = "tracy-client" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f6fc3baeac5d86ab90c772e9e30620fc653bf1864295029921a15ef478e6a5" +dependencies = [ + "loom", + "once_cell", + "tracy-client-sys", +] + +[[package]] +name = "tracy-client-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f7c95348f20c1c913d72157b3c6dee6ea3e30b3d19502c5a7f6d3f160dacbf" +dependencies = [ + "cc", + "windows-targets 0.48.5", ] [[package]] @@ -5492,7 +5695,7 @@ checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5535,6 +5738,24 @@ dependencies = [ "wit-bindgen-rt", ] +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -5557,7 +5778,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.104", + "syn", "wasm-bindgen-shared", ] @@ -5592,7 +5813,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5606,6 +5827,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.9.1", + "hashbrown 0.15.4", + "indexmap", + "semver", +] + [[package]] name = "web-sys" version = "0.3.77" @@ -5644,15 +5899,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.2", -] - [[package]] name = "webpki-roots" version = "1.0.2" @@ -5817,7 +6063,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5828,7 +6074,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5839,7 +6085,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5850,7 +6096,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -6211,6 +6457,26 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + [[package]] name = "wit-bindgen-rt" version = "0.39.0" @@ -6220,6 +6486,74 @@ dependencies = [ "bitflags 2.9.1", ] +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.9.1", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "writeable" version = "0.6.1" @@ -6247,33 +6581,34 @@ dependencies = [ [[package]] name = "x509-parser" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs", "data-encoding", - "der-parser 9.0.0", + "der-parser", "lazy_static", "nom", - "oid-registry 0.7.1", + "oid-registry", "rusticata-macros", - "thiserror 1.0.69", + "thiserror 2.0.12", "time", ] [[package]] name = "x509-parser" -version = "0.17.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" dependencies = [ - "asn1-rs 0.7.1", + "asn1-rs", "data-encoding", - "der-parser 10.0.0", + "der-parser", "lazy_static", "nom", - "oid-registry 0.8.1", + "oid-registry", + "ring", "rusticata-macros", "thiserror 2.0.12", "time", @@ -6349,7 +6684,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "synstructure", ] @@ -6370,7 +6705,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -6390,7 +6725,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "synstructure", ] @@ -6430,5 +6765,30 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", +] + +[[package]] +name = "zkvm-jetpack" +version = "0.1.0" +source = "git+https://github.com/swpsco/nockchain.git?rev=9eb98e9324e3101f16f38346cd5ace73d7e30adf#9eb98e9324e3101f16f38346cd5ace73d7e30adf" +dependencies = [ + "argon2", + "bitvec", + "bs58", + "bytes", + "either", + "hex-literal", + "ibig", + "nockchain-math", + "nockvm", + "nockvm_macros", + "noun-serde", + "num-traits", + "once_cell", + "quickcheck", + "rayon", + "smallvec", + "strum", + "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index 5e9e061..149505d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,5 +16,5 @@ uuid = { version = "1.6.1", features = ["v4", "serde"] } bytes = { version = "1.10.1" } # nockchain -nockchain-libp2p-io = { git = "https://github.com/swpsco/nockchain.git", rev = "9eb98e9324e3101f16f38346cd5ace73d7e30adf", package = "nockchain-libp2p-io" } -nockapp = { git = "https://github.com/swpsco/nockchain.git", rev = "9eb98e9324e3101f16f38346cd5ace73d7e30adf", package = "nockapp" } +nockchain-libp2p-io = { git = "https://github.com/swpsco/nockchain.git", rev = "d2a922cfd6812f9fb320aa0cb0de951272063475", package = "nockchain-libp2p-io" } +nockapp = { git = "https://github.com/swpsco/nockchain.git", rev = "d2a922cfd6812f9fb320aa0cb0de951272063475", package = "nockapp" } diff --git a/README.md b/README.md index 649eda8..b713cb8 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # Quiver Protocol -A simple quic protocol for nockpool mining. [Nockpool](https://nockpool.com/) \ No newline at end of file +A simple quic protocol for nockpool mining. [Nockpool](https://nockpool.com/) + +## Stream Model +- Bi stream 1: authentication (`api_key` -> `authenticated|rejected`) +- Bi stream 2: device info (`DeviceInfo` -> `accepted|rejected`) +- Uni stream: server-pushed template updates +- Bi streams (client-opened): submission request/response pairs +- Optional long-lived bi stream: telemetry frames (marker-prefixed) diff --git a/src/client.rs b/src/client.rs index de28e2c..22b9120 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,20 +1,20 @@ use std::net::SocketAddr; -use std::sync::Arc; use std::str::FromStr; +use std::sync::Arc; use std::time::Duration; use anyhow::Result; use quinn::crypto::rustls::QuicClientConfig; use quinn::{ClientConfig, Connection, Endpoint, IdleTimeout, TransportConfig}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tracing::{info, error}; +use tracing::{debug, error, info, warn}; use crate::device_info::DeviceInfo; -use crate::types::{Template, Submission, SubmissionResponse}; +use crate::insecure::SkipServerVerification; use crate::new_job::NewJobConsumer; use crate::submission::{SubmissionProvider, SubmissionResponseHandler}; -use crate::insecure::SkipServerVerification; - +use crate::telemetry::{TelemetryProvider, TELEMETRY_FRAME_MAX_BYTES, TELEMETRY_STREAM_MARKER}; +use crate::types::{Submission, SubmissionResponse, Template}; #[derive(Debug)] pub struct QuiverClient { @@ -24,6 +24,7 @@ pub struct QuiverClient { new_job_consumer: Arc, submission_provider: Arc, submission_response_handler: Arc, + telemetry_provider: Option>, } impl QuiverClient { @@ -34,6 +35,7 @@ impl QuiverClient { new_job_consumer: Arc, submission_provider: Arc, submission_response_handler: Arc, + telemetry_provider: Option>, ) -> Self { Self { conn, @@ -42,6 +44,7 @@ impl QuiverClient { new_job_consumer, submission_provider, submission_response_handler, + telemetry_provider, } } @@ -59,7 +62,9 @@ impl QuiverClient { // --- Device Info Transaction --- info!("sending device info..."); let (mut send_device, mut recv_device) = self.conn.open_bi().await?; - send_device.write_all(&bincode::serialize(&self.device_info)?).await?; + send_device + .write_all(&bincode::serialize(&self.device_info)?) + .await?; send_device.finish()?; let device_res = String::from_utf8(recv_device.read_to_end(50).await?)?; if device_res != "accepted" { @@ -68,8 +73,20 @@ impl QuiverClient { info!("Client authenticated and ready for work."); + // Telemetry stream is intentionally best-effort and detached. + // + // If telemetry transport fails for any reason, mining and share submission + // must continue uninterrupted. The background task handles retries and + // stream re-open logic internally. + if let Some(provider) = self.telemetry_provider.clone() { + tokio::spawn(run_telemetry_stream(self.conn.clone(), provider)); + } + // Spawn the background task to receive new jobs. - let mut job_handle = tokio::spawn(receive_jobs(self.conn.clone(), self.new_job_consumer.clone())); + let mut job_handle = tokio::spawn(receive_jobs( + self.conn.clone(), + self.new_job_consumer.clone(), + )); loop { tokio::select! { @@ -119,15 +136,118 @@ impl QuiverClient { } } +/// Drive the long-lived telemetry stream over quiver. +/// +/// This function intentionally never returns an error to callers. It loops and +/// self-recovers until the main connection closes. +async fn run_telemetry_stream(conn: Connection, provider: Arc) { + let reopen_backoff = Duration::from_secs(2); + let provider_error_backoff = Duration::from_secs(1); + + loop { + // If the connection closes, this branch wins and the telemetry task exits. + let stream_result = tokio::select! { + _ = conn.closed() => { + debug!("Telemetry stream task exiting: connection closed"); + return; + } + stream = conn.open_bi() => stream, + }; + + let (mut send, _recv) = match stream_result { + Ok(parts) => parts, + Err(e) => { + warn!("Telemetry stream open failed, retrying: {}", e); + tokio::select! { + _ = conn.closed() => return, + _ = tokio::time::sleep(reopen_backoff) => {} + } + continue; + } + }; + + // The first byte is a stream discriminator so the server can demultiplex + // telemetry vs legacy submission streams without breaking old clients. + if let Err(e) = send.write_u8(TELEMETRY_STREAM_MARKER).await { + warn!("Failed to write telemetry marker, reopening stream: {}", e); + tokio::select! { + _ = conn.closed() => return, + _ = tokio::time::sleep(reopen_backoff) => {} + } + continue; + } + + debug!("Telemetry stream established"); + + loop { + // Wait for either connection closure or the next telemetry sample. + let next_sample = tokio::select! { + _ = conn.closed() => { + debug!("Telemetry stream task exiting: connection closed"); + return; + } + sample = provider.next_telemetry() => sample, + }; + + let telemetry = match next_sample { + Ok(sample) => sample, + Err(e) => { + // Provider-side failures are treated as transient. + warn!("Telemetry provider failed to produce sample: {}", e); + tokio::time::sleep(provider_error_backoff).await; + continue; + } + }; + + let payload = match bincode::serialize(&telemetry) { + Ok(payload) => payload, + Err(e) => { + warn!("Failed to serialize telemetry sample: {}", e); + continue; + } + }; + + if payload.len() as u32 > TELEMETRY_FRAME_MAX_BYTES { + warn!( + "Telemetry frame too large ({} bytes > {} bytes), dropping sample", + payload.len(), + TELEMETRY_FRAME_MAX_BYTES + ); + continue; + } + + // Frame format: [u32 payload_len][payload_bytes] + // We keep this compact and binary for low overhead under steady load. + if let Err(e) = send.write_u32(payload.len() as u32).await { + warn!("Telemetry stream write(length) failed: {}", e); + break; + } + if let Err(e) = send.write_all(&payload).await { + warn!("Telemetry stream write(payload) failed: {}", e); + break; + } + } + + // The current stream is broken; close locally and reopen on next loop. + let _ = send.finish(); + tokio::select! { + _ = conn.closed() => return, + _ = tokio::time::sleep(reopen_backoff) => {} + } + } +} + /// Handle the network I/O for a single submission. async fn handle_one_submission( conn: Connection, submission: Submission, - handler: Arc + handler: Arc, ) -> Result<()> { let (mut send_submission, mut recv_submission) = conn.open_bi().await?; let submission_bytes = bincode::serialize(&submission)?; - send_submission.write_u32(submission_bytes.len() as u32).await?; + send_submission + .write_u32(submission_bytes.len() as u32) + .await?; send_submission.write_all(&submission_bytes).await?; send_submission.finish()?; @@ -140,7 +260,6 @@ async fn handle_one_submission( Ok(()) } - pub async fn run( insecure: bool, server_address: String, @@ -150,6 +269,35 @@ pub async fn run( new_job_consumer: Arc, submission_provider: Arc, submission_response_handler: Arc, +) -> Result<()> { + run_with_telemetry( + insecure, + server_address, + client_address, + key, + device_info, + new_job_consumer, + submission_provider, + submission_response_handler, + None, + ) + .await +} + +/// Start a quiver client with optional telemetry streaming support. +/// +/// This is a superset of `run()` and preserves backward compatibility by letting +/// existing callers pass `None` for telemetry. +pub async fn run_with_telemetry( + insecure: bool, + server_address: String, + client_address: String, + key: String, + device_info: DeviceInfo, + new_job_consumer: Arc, + submission_provider: Arc, + submission_response_handler: Arc, + telemetry_provider: Option>, ) -> Result<()> { let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); let mut endpoint = Endpoint::client(SocketAddr::from_str(&client_address)?)?; @@ -157,7 +305,7 @@ pub async fn run( let mut transport = TransportConfig::default(); transport.keep_alive_interval(Some(Duration::from_secs(10))); // send pingz transport.max_idle_timeout(Some( - IdleTimeout::try_from(Duration::from_secs(120)).expect("idle-timeout range") + IdleTimeout::try_from(Duration::from_secs(120)).expect("idle-timeout range"), )); let transport = Arc::new(transport); @@ -172,22 +320,8 @@ pub async fn run( ClientConfig::new(Arc::new(QuicClientConfig::try_from(crypto)?)) }; client_cfg.transport_config(transport); - endpoint.set_default_client_config(client_cfg); - if !insecure { - let config = ClientConfig::with_platform_verifier(); - endpoint.set_default_client_config(config); - } else { - let crypto = rustls::ClientConfig::builder() - .dangerous() - .with_custom_certificate_verifier(SkipServerVerification::new()) - .with_no_client_auth(); - endpoint.set_default_client_config(ClientConfig::new(Arc::new( - QuicClientConfig::try_from(crypto)?, - ))); - } - let remote_address = tokio::net::lookup_host(server_address.as_str()) .await? .next() @@ -201,16 +335,25 @@ pub async fn run( info!("Connecting to nockpool at {}", server_address); - let connection = endpoint - .connect(remote_address, host)? - .await?; + let connection = endpoint.connect(remote_address, host)?.await?; info!("Connected to nockpool at {}", server_address); - let mut client = QuiverClient::new(connection, key, device_info, new_job_consumer, submission_provider, submission_response_handler); + let mut client = QuiverClient::new( + connection, + key, + device_info, + new_job_consumer, + submission_provider, + submission_response_handler, + telemetry_provider, + ); client.serve().await } -async fn receive_jobs(conn: quinn::Connection, new_job_consumer: Arc) -> Result<()> { +async fn receive_jobs( + conn: quinn::Connection, + new_job_consumer: Arc, +) -> Result<()> { loop { let mut recv = match conn.accept_uni().await { Ok(s) => { @@ -223,17 +366,18 @@ async fn receive_jobs(conn: quinn::Connection, new_job_consumer: Arc len, Err(e) => { // distinguish eof vs reset vs connection-closed for diagnostics - use std::error::Error as _; let mut src = (&e as &dyn std::error::Error).source(); while let Some(inner) = src { - if let Some(quinn::ReadError::Reset(code)) = inner.downcast_ref::() { + if let Some(quinn::ReadError::Reset(code)) = + inner.downcast_ref::() + { tracing::warn!("job stream reset by peer: {code:?}"); break; } diff --git a/src/lib.rs b/src/lib.rs index 3d28757..7da4a56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,9 @@ -pub mod server; -pub mod client; pub mod auth; +pub mod client; pub mod device_info; +pub mod insecure; pub mod new_job; +pub mod server; pub mod submission; +pub mod telemetry; pub mod types; -pub mod insecure; \ No newline at end of file diff --git a/src/server.rs b/src/server.rs index a351d2d..8eba759 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,19 +1,28 @@ -use tracing::{info, error}; use anyhow::Result; -use quinn::{ServerConfig, Endpoint, Connection, TransportConfig}; +use bytes::Bytes; +use quinn::{Connection, Endpoint, ServerConfig, TransportConfig}; use std::net::SocketAddr; +use std::str::FromStr; use std::sync::Arc; use std::time::Duration; use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use bytes::Bytes; -use std::str::FromStr; +use tracing::{error, info, warn}; -use rustls::pki_types::{CertificateDer, PrivateKeyDer}; use crate::auth::{Authenticator, ConnectionGuard}; use crate::device_info::{DeviceInfo, DeviceInfoUpdater}; use crate::new_job::NewJobProvider; -use crate::types::{Template, Submission, SubmissionResponse, AccountInformation}; use crate::submission::SubmissionConsumer; +use crate::telemetry::{ + TelemetryConsumer, TelemetryData, TELEMETRY_FRAME_MAX_BYTES, TELEMETRY_STREAM_MARKER, +}; +use crate::types::{AccountInformation, Submission, SubmissionResponse, Template}; +use rustls::pki_types::{CertificateDer, PrivateKeyDer}; + +/// Conservative upper bound for a single submission frame. +/// +/// Typical submissions are much smaller. This protects the server against +/// accidental or malicious oversized frame allocations. +const SUBMISSION_FRAME_MAX_BYTES: u32 = 2 * 1024 * 1024; struct QuiverInstance { conn: Connection, @@ -24,6 +33,7 @@ struct QuiverInstance { device_info_updater: Arc, new_job_provider: Arc, submission_consumer: Arc, + telemetry_consumer: Option>, } impl QuiverInstance { @@ -33,6 +43,7 @@ impl QuiverInstance { device_info_updater: Arc, new_job_provider: Arc, submission_consumer: Arc, + telemetry_consumer: Option>, ) -> Self { Self { conn, @@ -43,6 +54,7 @@ impl QuiverInstance { device_info_updater, new_job_provider, submission_consumer, + telemetry_consumer, } } @@ -80,7 +92,11 @@ impl QuiverInstance { return Err(anyhow::anyhow!("no api key")); }; - match self.device_info_updater.update_device_info(&device_info, &api_key).await { + match self + .device_info_updater + .update_device_info(&device_info, &api_key) + .await + { Ok(_) => { send.write_all(b"accepted").await?; send.finish()?; @@ -94,57 +110,51 @@ impl QuiverInstance { } } async fn handle_work(&mut self) -> Result<()> { - // New job pusher + // New job pusher on a dedicated unidirectional stream. + // This stream is independent from bidirectional submission/telemetry streams. let new_job_provider = self.new_job_provider.clone(); let conn = self.conn.clone(); tokio::spawn(async move { if let Err(e) = push_jobs(conn, new_job_provider).await { - // if error is connection closed, we can just break the loop if e.to_string().contains("connection closed") { return; } + warn!("job pusher exited with error: {}", e); } }); + let conn = self.conn.clone(); - // Submission management + let account_information = self.account_information.clone(); + let api_key = self.api_key.clone(); + + // Bidirectional stream multiplexer. + // Each inbound bi stream is either: + // - legacy submission stream (length-prefixed submission frame), or + // - telemetry stream (marker byte + repeating telemetry frames). loop { - let (mut send_submission, mut recv_submission) = match conn.accept_bi().await { + let (send_stream, recv_stream) = match conn.accept_bi().await { Ok(s) => s, Err(_) => break, // connection closed }; - let submission_consumer = self.submission_consumer.clone(); - let account_information = self.account_information.clone(); - tokio::spawn(async move { - let len = match recv_submission.read_u32().await { - Ok(len) => len, - Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => { - info!("Submission stream closed."); - return; - } - Err(e) => { - error!("submission stream error: {:?}", e); - return; - } - }; - - let submission: Submission = { - let mut buf = vec![0; len as usize]; - recv_submission.read_exact(&mut buf).await.expect("failed to read submission"); - bincode::deserialize(&buf).expect("failed to deserialize submission") - // buf is dropped here, freeing ~110KB immediately - }; - - let Some(account_information) = account_information.clone() else { - error!("no account information"); - return; - }; - let response: SubmissionResponse = submission_consumer.process(submission, account_information).await.expect("failed to process submission"); + let submission_consumer = self.submission_consumer.clone(); + let telemetry_consumer = self.telemetry_consumer.clone(); + let account_information = account_information.clone(); + let api_key = api_key.clone(); - let response_bytes = bincode::serialize(&response).expect("failed to serialize response"); - send_submission.write_u32(response_bytes.len() as u32).await.expect("failed to write response length"); - send_submission.write_all(&response_bytes).await.expect("failed to write response"); - let _ = send_submission.finish(); + tokio::spawn(async move { + if let Err(e) = dispatch_bi_stream( + send_stream, + recv_stream, + submission_consumer, + telemetry_consumer, + account_information, + api_key, + ) + .await + { + warn!("bi stream handler exited with error: {}", e); + } }); } Ok(()) @@ -163,8 +173,19 @@ impl QuiverInstance { } // take the last 8 characters of the api key - let truncated_api_key = self.api_key.as_ref().unwrap().chars().rev().take(8).collect::(); - info!("{:?} put to work with key {:?}", self.account_information.as_ref().unwrap().user_uuid, truncated_api_key); + let truncated_api_key = self + .api_key + .as_ref() + .unwrap() + .chars() + .rev() + .take(8) + .collect::(); + info!( + "{:?} put to work with key {:?}", + self.account_information.as_ref().unwrap().user_uuid, + truncated_api_key + ); // Ready for work. self.handle_work().await @@ -179,6 +200,33 @@ pub async fn run( device_info_updater: Arc, new_job_provider: Arc, submission_consumer: Arc, +) -> Result<()> { + run_with_telemetry( + address, + certs, + key, + authenticator, + device_info_updater, + new_job_provider, + submission_consumer, + None, + ) + .await +} + +/// Start the quiver server with optional telemetry consumer support. +/// +/// Existing callers can continue using `run()` without telemetry by passing `None` +/// through the compatibility wrapper above. +pub async fn run_with_telemetry( + address: String, + certs: Vec>, + key: PrivateKeyDer<'static>, + authenticator: Arc, + device_info_updater: Arc, + new_job_provider: Arc, + submission_consumer: Arc, + telemetry_consumer: Option>, ) -> Result<()> { info!("quiver listening..."); @@ -199,7 +247,7 @@ pub async fn run( config.incoming_buffer_size_total(1024 * 1024 * 1024); let endpoint = Endpoint::server(config, SocketAddr::from_str(&address)?)?; - + // Start iterating over incoming connections. while let Some(conn) = endpoint.accept().await { let Ok(connection) = conn.await else { @@ -209,8 +257,16 @@ pub async fn run( let device_info_updater = Arc::clone(&device_info_updater); let new_job_provider = Arc::clone(&new_job_provider); let submission_consumer = Arc::clone(&submission_consumer); + let telemetry_consumer = telemetry_consumer.clone(); tokio::spawn(async move { - let mut instance = QuiverInstance::new(connection, authenticator, device_info_updater, new_job_provider, submission_consumer); + let mut instance = QuiverInstance::new( + connection, + authenticator, + device_info_updater, + new_job_provider, + submission_consumer, + telemetry_consumer, + ); if let Err(e) = instance.serve().await { error!("error: {:?}", e); } @@ -219,12 +275,155 @@ pub async fn run( Ok(()) } -async fn push_jobs( - conn: Connection, - new_job_provider: Arc, +/// Route an incoming bidirectional stream to either submission or telemetry handling. +async fn dispatch_bi_stream( + mut send: quinn::SendStream, + mut recv: quinn::RecvStream, + submission_consumer: Arc, + telemetry_consumer: Option>, + account_information: Option, + api_key: Option, ) -> Result<()> { + let first_byte = match recv.read_u8().await { + Ok(byte) => byte, + Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => { + info!("bidirectional stream closed before payload"); + return Ok(()); + } + Err(e) => return Err(e.into()), + }; + + // Marker-prefixed stream: dedicated long-lived telemetry transport. + if first_byte == TELEMETRY_STREAM_MARKER { + let Some(telemetry_consumer) = telemetry_consumer else { + warn!("received telemetry stream but no telemetry consumer is configured"); + return Ok(()); + }; + let Some(account_information) = account_information else { + return Err(anyhow::anyhow!( + "telemetry stream received without account information" + )); + }; + let Some(api_key) = api_key else { + return Err(anyhow::anyhow!("telemetry stream received without api key")); + }; + + // Telemetry is one-way from client -> server. + // Close send-half to signal there will be no server response payloads. + let _ = send.finish(); + return handle_telemetry_stream(recv, telemetry_consumer, account_information, api_key) + .await; + } + + // Legacy submission stream: first byte belongs to u32 frame length. + handle_submission_stream( + first_byte, + &mut send, + &mut recv, + submission_consumer, + account_information, + ) + .await +} + +/// Handle one legacy submission stream where frame length starts at the first byte. +async fn handle_submission_stream( + first_len_byte: u8, + send: &mut quinn::SendStream, + recv: &mut quinn::RecvStream, + submission_consumer: Arc, + account_information: Option, +) -> Result<()> { + let Some(account_information) = account_information else { + return Err(anyhow::anyhow!( + "submission stream received without account information" + )); + }; + + // Reconstruct the big-endian u32 length from the already-consumed first byte. + let mut len_tail = [0u8; 3]; + recv.read_exact(&mut len_tail).await?; + let frame_len = u32::from_be_bytes([first_len_byte, len_tail[0], len_tail[1], len_tail[2]]); + + if frame_len == 0 { + return Err(anyhow::anyhow!("submission frame length is zero")); + } + if frame_len > SUBMISSION_FRAME_MAX_BYTES { + return Err(anyhow::anyhow!( + "submission frame too large: {} > {}", + frame_len, + SUBMISSION_FRAME_MAX_BYTES + )); + } + + let mut buf = vec![0; frame_len as usize]; + recv.read_exact(&mut buf).await?; + let submission: Submission = bincode::deserialize(&buf)?; + + let response: SubmissionResponse = submission_consumer + .process(submission, account_information) + .await?; + let response_bytes = bincode::serialize(&response)?; + send.write_u32(response_bytes.len() as u32).await?; + send.write_all(&response_bytes).await?; + let _ = send.finish(); + Ok(()) +} + +/// Handle a marker-prefixed telemetry stream with repeating length-delimited frames. +async fn handle_telemetry_stream( + mut recv: quinn::RecvStream, + telemetry_consumer: Arc, + account_information: AccountInformation, + api_key: String, +) -> Result<()> { + loop { + let frame_len = match recv.read_u32().await { + Ok(len) => len, + Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => { + info!("telemetry stream closed by peer"); + return Ok(()); + } + Err(e) => return Err(e.into()), + }; + + if frame_len == 0 { + warn!("received empty telemetry frame"); + continue; + } + + if frame_len > TELEMETRY_FRAME_MAX_BYTES { + return Err(anyhow::anyhow!( + "telemetry frame too large: {} > {}", + frame_len, + TELEMETRY_FRAME_MAX_BYTES + )); + } + + let mut buf = vec![0; frame_len as usize]; + recv.read_exact(&mut buf).await?; + let telemetry: TelemetryData = bincode::deserialize(&buf)?; + + // Consumer failures are logged and ignored so a single bad write does + // not terminate telemetry transport for that miner connection. + if let Err(e) = telemetry_consumer + .process_telemetry(telemetry, account_information.clone(), &api_key) + .await + { + warn!("telemetry consumer failed: {}", e); + } + } +} + +async fn push_jobs(conn: Connection, new_job_provider: Arc) -> Result<()> { let mut send = conn.open_uni().await?; - let mut current_template = Template::new(Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new()); + let mut current_template = Template::new( + Bytes::new(), + Bytes::new(), + Bytes::new(), + Bytes::new(), + Bytes::new(), + ); loop { let template = new_job_provider.get(current_template.clone()).await; let t = match template { @@ -239,4 +438,4 @@ async fn push_jobs( send.write_all(&buf).await?; current_template = t; } -} \ No newline at end of file +} diff --git a/src/telemetry.rs b/src/telemetry.rs new file mode 100644 index 0000000..e48229c --- /dev/null +++ b/src/telemetry.rs @@ -0,0 +1,58 @@ +use anyhow::Result; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; + +use crate::types::AccountInformation; + +/// Stream discriminator used on client-opened bi-directional streams. +/// +/// Legacy clients do not send a discriminator byte and begin their submission +/// stream with a 4-byte length prefix. The server uses this value to identify +/// telemetry streams while preserving backward compatibility with legacy +/// submission framing. +pub const TELEMETRY_STREAM_MARKER: u8 = 0xF1; + +/// Upper bound for a serialized telemetry message. +/// +/// Telemetry payloads are intentionally small (device metadata + current rate). +/// A hard cap prevents accidental memory blowups if malformed data arrives. +pub const TELEMETRY_FRAME_MAX_BYTES: u32 = 64 * 1024; + +/// Telemetry snapshot sent by miners over the dedicated quiver telemetry stream. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct TelemetryData { + pub device_os: String, + pub device_cpu: String, + pub device_ram_capacity_gb: u64, + pub device_proof_rate_per_sec: f64, + pub zkvm_jetpack_hash: Option, + pub miner_version: String, + pub gpu_info: Option, + pub num_threads: Option, + /// Miner-side wall clock used by downstream writers for ordering safeguards. + pub sent_at_unix_ms: i64, +} + +/// Pull-based telemetry producer for the quiver client. +/// +/// Implementations are expected to block until the next telemetry sample should +/// be sent. This keeps scheduling policy (intervals, startup delay, etc.) in the +/// application layer and keeps the quiver crate transport-only. +#[async_trait] +pub trait TelemetryProvider: Send + Sync + std::fmt::Debug { + async fn next_telemetry(&self) -> Result; +} + +/// Telemetry sink hook for the quiver server. +/// +/// The protocol crate does not know or care where telemetry is persisted. +/// Implementers can route events to NATS, Kafka, direct DB updates, etc. +#[async_trait] +pub trait TelemetryConsumer: Send + Sync { + async fn process_telemetry( + &self, + telemetry: TelemetryData, + account_information: AccountInformation, + api_key: &str, + ) -> Result<()>; +}