From 51887aa3fb198cbe067df380111afdd980e0b52b Mon Sep 17 00:00:00 2001 From: r4bbit <445106+0x-r4bbit@users.noreply.github.com> Date: Tue, 2 Jun 2026 18:07:45 +0200 Subject: [PATCH] feat(twap-oracle): implement PublishPrice with real tick-to-price conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PublishPrice — a permissionless instruction that computes the TWAP over a PriceObservations buffer and writes it to the consumer-facing OraclePriceAccount. Because each observations account is calibrated to a specific window_duration via its sampling guard, the oldest valid entry is always the natural window start, so the TWAP is computed over the full buffer span with no boundary search: t2 = most recent observation (write_index - 1, wrapping) t1 = oldest valid entry (0 if not full, write_index if full) twap_tick = (t2.tick_cumulative - t1.tick_cumulative) / (t2.ts - t1.ts) If fewer than two observations exist the call is a silent no-op, leaving the price account at timestamp = 0 (the uninitialized signal consumers already reject). While the buffer is young the TWAP is computed over the available span, which may be shorter than the requested window. The TWAP tick is converted to an actual price ratio via the Uniswap v3 sqrtPriceX96 representation (pure integer, zkVM-safe): get_sqrt_ratio_at_tick(tick) then sqrtPriceX96^2 / 2^128, yielding a Q64.64 fixed-point ratio stored in OraclePriceAccount.price. The OraclePriceAccount stays source-agnostic — no tick or Uniswap framing leaks into the standard. Out-of-range ticks clamp; ratios above 2^64 saturate at u128::MAX. Adds PRICE_FRACTIONAL_BITS = 64; removes the placeholder TWAP_PRICE_BIAS / oracle_price_to_tick bias encoding. Pulls in uniswap_v3_math 0.6.2 and alloy-primitives for the conversion. Pins ruint to =1.17.0 (transitive via alloy-primitives): 1.18 raised its MSRV to rustc 1.90 but the risc0 guest toolchain ships 1.88. Guest build verified for riscv32im. Closes #117 --- Cargo.lock | 787 +++++++++++++++-- artifacts/stablecoin-idl.json | 24 +- artifacts/twap_oracle-idl.json | 33 + programs/stablecoin/methods/guest/Cargo.lock | 778 +++++++++++++++-- programs/twap_oracle/core/Cargo.toml | 6 + programs/twap_oracle/core/src/lib.rs | 142 ++++ programs/twap_oracle/methods/guest/Cargo.lock | 788 ++++++++++++++++-- .../methods/guest/src/bin/twap_oracle.rs | 27 + programs/twap_oracle/src/lib.rs | 1 + programs/twap_oracle/src/publish_price.rs | 510 ++++++++++++ 10 files changed, 2918 insertions(+), 178 deletions(-) create mode 100644 programs/twap_oracle/src/publish_price.rs diff --git a/Cargo.lock b/Cargo.lock index e58ef1f..3727234 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,44 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy-primitives" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4885c1409b6936c4898e646ef58baf6ec54edaf6d8179f79df805a7b85b7cf3e" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "foldhash 0.2.0", + "hashbrown 0.17.1", + "indexmap 2.14.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.9.4", + "rapidhash", + "ruint", + "rustc-hash", + "secp256k1", + "serde", + "sha3", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" +dependencies = [ + "arrayvec", + "bytes", +] + [[package]] name = "amm-methods" version = "0.1.0" @@ -81,9 +119,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" dependencies = [ "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-r1cs-std", - "ark-std", + "ark-std 0.5.0", ] [[package]] @@ -95,14 +133,14 @@ dependencies = [ "ahash", "ark-crypto-primitives-macros", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-serialize", + "ark-serialize 0.5.0", "ark-snark", - "ark-std", + "ark-std 0.5.0", "blake2", "derivative", - "digest", + "digest 0.10.7", "fnv", "merlin", "sha2", @@ -126,10 +164,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" dependencies = [ "ahash", - "ark-ff", + "ark-ff 0.5.0", "ark-poly", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "educe", "fnv", "hashbrown 0.15.5", @@ -140,18 +178,56 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + [[package]] name = "ark-ff" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "arrayvec", - "digest", + "digest 0.10.7", "educe", "itertools 0.13.0", "num-bigint", @@ -160,6 +236,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-asm" version = "0.5.0" @@ -170,6 +266,31 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-macros" version = "0.5.0" @@ -191,11 +312,11 @@ checksum = "88f1d0f3a534bb54188b8dcc104307db6c56cdae574ddc3212aec0625740fc7e" dependencies = [ "ark-crypto-primitives", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-poly", "ark-relations", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", ] [[package]] @@ -205,9 +326,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" dependencies = [ "ahash", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "educe", "fnv", "hashbrown 0.15.5", @@ -220,9 +341,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" dependencies = [ "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-std", + "ark-std 0.5.0", "educe", "num-bigint", "num-integer", @@ -236,12 +357,33 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" dependencies = [ - "ark-ff", - "ark-std", + "ark-ff 0.5.0", + "ark-std 0.5.0", "tracing", "tracing-subscriber", ] +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + [[package]] name = "ark-serialize" version = "0.5.0" @@ -249,9 +391,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ "ark-serialize-derive", - "ark-std", + "ark-std 0.5.0", "arrayvec", - "digest", + "digest 0.10.7", "num-bigint", ] @@ -272,10 +414,30 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d368e2848c2d4c129ce7679a7d0d2d612b6a274d3ea6a13bad4445d61b381b88" dependencies = [ - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.6", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.6", ] [[package]] @@ -334,6 +496,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "autocfg" version = "1.5.1" @@ -373,12 +546,37 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + [[package]] name = "bit-vec" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitcoin-io" +version = "0.1.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11301df0b06f22dea7bb1916403fdd88a371031e495c49b8f96931b28189e175" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9901a56e133a1fc86eeb1113e2591f45f4682451ca893bff494d2f88918e3f" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -391,13 +589,25 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -476,6 +686,12 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + [[package]] name = "bytemuck" version = "1.25.0" @@ -546,7 +762,7 @@ checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.28", "serde", "serde_json", "thiserror 2.0.18", @@ -626,12 +842,54 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "const-hex" +version = "1.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e2a781ebdf4467d1428dc4593067825fb646f6871475098d8577421af73558" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "proptest", + "serde_core", +] + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_format" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -677,6 +935,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -855,13 +1119,23 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.1", "syn 2.0.117", "unicode-xid", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" @@ -874,6 +1148,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.2", +] + [[package]] name = "dirs" version = "6.0.0" @@ -892,7 +1176,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -942,7 +1226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", "rfc6979", "serdect", @@ -982,7 +1266,7 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", @@ -1049,7 +1333,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", ] [[package]] @@ -1058,6 +1352,28 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "ff" version = "0.13.1" @@ -1074,6 +1390,18 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.6", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1086,6 +1414,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.5.0" @@ -1122,6 +1456,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures-channel" version = "0.3.32" @@ -1258,7 +1598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -1266,6 +1606,9 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "hashlink" @@ -1288,6 +1631,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "0.4.1" @@ -1300,7 +1652,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -1558,12 +1910,38 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "include_bytes_aligned" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + [[package]] name = "indexmap" version = "1.9.3" @@ -1618,6 +1996,15 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1678,6 +2065,41 @@ dependencies = [ "cpufeatures 0.2.17", ] +[[package]] +name = "keccak" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", +] + +[[package]] +name = "keccak-asm" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1766b89733097006f3a1388a02849865d6bc98c89273cb622e29fdd209922183" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + [[package]] name = "lazy-regex" version = "3.6.0" @@ -1794,7 +2216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", - "keccak", + "keccak 0.1.6", "rand_core 0.6.4", "zeroize", ] @@ -1974,6 +2396,34 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "paste" version = "1.0.15" @@ -1995,6 +2445,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -2068,6 +2528,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -2104,11 +2575,16 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ + "bit-set", + "bit-vec", "bitflags 2.11.1", "num-traits", "rand 0.9.4", "rand_chacha 0.9.0", "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", "unarray", ] @@ -2135,6 +2611,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quinn" version = "0.11.9" @@ -2211,6 +2693,12 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.6" @@ -2279,6 +2767,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rapidhash" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +dependencies = [ + "rustversion", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -2422,7 +2919,7 @@ dependencies = [ "risc0-zkp", "risc0-zkvm-platform", "ruint", - "semver", + "semver 1.0.28", "serde", "tracing", ] @@ -2444,7 +2941,7 @@ dependencies = [ "risc0-zkp", "risc0-zkvm-platform", "rzup", - "semver", + "semver 1.0.28", "serde", "serde_json", "stability", @@ -2519,9 +3016,9 @@ dependencies = [ "anyhow", "ark-bn254", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-groth16", - "ark-serialize", + "ark-serialize 0.5.0", "bytemuck", "hex", "num-bigint", @@ -2553,7 +3050,7 @@ dependencies = [ "borsh", "bytemuck", "cfg-if", - "digest", + "digest 0.10.7", "hex", "hex-literal", "metal", @@ -2595,7 +3092,7 @@ dependencies = [ "risc0-zkvm-platform", "rrs-lib", "rzup", - "semver", + "semver 1.0.28", "serde", "sha2", "stability", @@ -2619,6 +3116,16 @@ dependencies = [ "stability", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "rrs-lib" version = "0.1.0" @@ -2636,7 +3143,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid", - "digest", + "digest 0.10.7", "num-bigint-dig", "num-integer", "num-traits", @@ -2651,14 +3158,27 @@ dependencies = [ [[package]] name = "ruint" -version = "1.18.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "ark-ff 0.5.0", "borsh", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", "proptest", "rand 0.8.6", "rand 0.9.4", + "rlp", "ruint-macro", "serde_core", "valuable", @@ -2677,13 +3197,28 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.28", ] [[package]] @@ -2696,7 +3231,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -2740,6 +3275,18 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.23" @@ -2754,7 +3301,7 @@ checksum = "5d2aed296f203fa64bcb4b52069356dd86d6ec578593985b919b6995bee1f0ae" dependencies = [ "hex", "rsa", - "semver", + "semver 1.0.28", "serde", "serde_with", "sha2", @@ -2804,6 +3351,35 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3c81b43dc2d8877c216a3fccf76677ee1ebccd429566d3e67447290d0c42b2" +dependencies = [ + "bitcoin_hashes", + "rand 0.9.4", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb913707158fadaf0d8702c2db0e857de66eb003ccfdda5924b5f5ac98efb38" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.28" @@ -2814,6 +3390,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.228" @@ -2928,7 +3513,27 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures 0.2.17", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" +dependencies = [ + "digest 0.11.3", + "keccak 0.2.0", +] + +[[package]] +name = "sha3-asm" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3f15d4e239ebe08413eed880e0f9b5af4b40ee0472543320efa91d488e96a7" +dependencies = [ + "cc", + "cfg-if", ] [[package]] @@ -2943,7 +3548,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -2966,7 +3571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3059,6 +3664,12 @@ dependencies = [ "token_core", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.1" @@ -3134,6 +3745,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.27.0" @@ -3144,7 +3761,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3484,11 +4101,14 @@ dependencies = [ name = "twap_oracle_core" version = "0.1.0" dependencies = [ + "alloy-primitives", "borsh", "nssa_core", "risc0-zkvm", + "ruint", "serde", "spel-framework-macros", + "uniswap_v3_math", ] [[package]] @@ -3506,6 +4126,24 @@ version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unarray" version = "0.1.4" @@ -3518,12 +4156,29 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "uniswap_v3_math" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e393498a831893ce69ed6e1d06615e400bd1e8f97e9fcd113324f2d610fe6d45" +dependencies = [ + "alloy-primitives", + "eyre", + "thiserror 2.0.18", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -3560,6 +4215,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "want" version = "0.3.1" @@ -3692,7 +4356,7 @@ dependencies = [ "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap 2.14.0", - "semver", + "semver 1.0.28", ] [[package]] @@ -4043,7 +4707,7 @@ dependencies = [ "id-arena", "indexmap 2.14.0", "log", - "semver", + "semver 1.0.28", "serde", "serde_derive", "serde_json", @@ -4057,6 +4721,15 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "yaml-rust2" version = "0.10.4" diff --git a/artifacts/stablecoin-idl.json b/artifacts/stablecoin-idl.json index 83e8342..1c3d9e8 100644 --- a/artifacts/stablecoin-idl.json +++ b/artifacts/stablecoin-idl.json @@ -342,6 +342,18 @@ } ], "types": [ + { + "name": "MetadataStandard", + "kind": "enum", + "variants": [ + { + "name": "Simple" + }, + { + "name": "Expanded" + } + ] + }, { "name": "ObservationEntry", "kind": "struct", @@ -355,18 +367,6 @@ "type": "i64" } ] - }, - { - "name": "MetadataStandard", - "kind": "enum", - "variants": [ - { - "name": "Simple" - }, - { - "name": "Expanded" - } - ] } ], "instruction_type": "stablecoin_core::Instruction" diff --git a/artifacts/twap_oracle-idl.json b/artifacts/twap_oracle-idl.json index c7f9095..8c605d4 100644 --- a/artifacts/twap_oracle-idl.json +++ b/artifacts/twap_oracle-idl.json @@ -95,6 +95,39 @@ } ] }, + { + "name": "publish_price", + "accounts": [ + { + "name": "price_observations", + "writable": false, + "signer": false, + "init": false + }, + { + "name": "oracle_price_account", + "writable": false, + "signer": false, + "init": false + }, + { + "name": "clock", + "writable": false, + "signer": false, + "init": false + } + ], + "args": [ + { + "name": "price_source_id", + "type": "account_id" + }, + { + "name": "window_duration", + "type": "u64" + } + ] + }, { "name": "record_tick", "accounts": [ diff --git a/programs/stablecoin/methods/guest/Cargo.lock b/programs/stablecoin/methods/guest/Cargo.lock index 95f28d8..952f359 100644 --- a/programs/stablecoin/methods/guest/Cargo.lock +++ b/programs/stablecoin/methods/guest/Cargo.lock @@ -29,6 +29,44 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy-primitives" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4885c1409b6936c4898e646ef58baf6ec54edaf6d8179f79df805a7b85b7cf3e" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "foldhash 0.2.0", + "hashbrown 0.17.1", + "indexmap 2.14.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.9.4", + "rapidhash", + "ruint", + "rustc-hash", + "secp256k1", + "serde", + "sha3", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" +dependencies = [ + "arrayvec", + "bytes", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -51,9 +89,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" dependencies = [ "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-r1cs-std", - "ark-std", + "ark-std 0.5.0", ] [[package]] @@ -65,14 +103,14 @@ dependencies = [ "ahash", "ark-crypto-primitives-macros", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-serialize", + "ark-serialize 0.5.0", "ark-snark", - "ark-std", + "ark-std 0.5.0", "blake2", "derivative", - "digest", + "digest 0.10.7", "fnv", "merlin", "sha2", @@ -96,10 +134,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" dependencies = [ "ahash", - "ark-ff", + "ark-ff 0.5.0", "ark-poly", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "educe", "fnv", "hashbrown 0.15.5", @@ -110,18 +148,56 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + [[package]] name = "ark-ff" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "arrayvec", - "digest", + "digest 0.10.7", "educe", "itertools 0.13.0", "num-bigint", @@ -130,6 +206,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-asm" version = "0.5.0" @@ -140,6 +236,31 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-macros" version = "0.5.0" @@ -161,11 +282,11 @@ checksum = "88f1d0f3a534bb54188b8dcc104307db6c56cdae574ddc3212aec0625740fc7e" dependencies = [ "ark-crypto-primitives", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-poly", "ark-relations", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", ] [[package]] @@ -175,9 +296,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" dependencies = [ "ahash", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "educe", "fnv", "hashbrown 0.15.5", @@ -190,9 +311,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" dependencies = [ "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-std", + "ark-std 0.5.0", "educe", "num-bigint", "num-integer", @@ -206,12 +327,33 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" dependencies = [ - "ark-ff", - "ark-std", + "ark-ff 0.5.0", + "ark-std 0.5.0", "tracing", "tracing-subscriber", ] +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + [[package]] name = "ark-serialize" version = "0.5.0" @@ -219,9 +361,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ "ark-serialize-derive", - "ark-std", + "ark-std 0.5.0", "arrayvec", - "digest", + "digest 0.10.7", "num-bigint", ] @@ -242,10 +384,30 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d368e2848c2d4c129ce7679a7d0d2d612b6a274d3ea6a13bad4445d61b381b88" dependencies = [ - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.6", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.6", ] [[package]] @@ -276,6 +438,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "autocfg" version = "1.5.1" @@ -315,12 +488,37 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + [[package]] name = "bit-vec" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitcoin-io" +version = "0.1.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11301df0b06f22dea7bb1916403fdd88a371031e495c49b8f96931b28189e175" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9901a56e133a1fc86eeb1113e2591f45f4682451ca893bff494d2f88918e3f" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -333,13 +531,25 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -418,6 +628,12 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + [[package]] name = "bytemuck" version = "1.25.0" @@ -488,7 +704,7 @@ checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.28", "serde", "serde_json", "thiserror 2.0.18", @@ -559,12 +775,54 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "const-hex" +version = "1.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e2a781ebdf4467d1428dc4593067825fb646f6871475098d8577421af73558" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "proptest", + "serde_core", +] + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_format" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -610,6 +868,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -788,13 +1052,23 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.1", "syn 2.0.117", "unicode-xid", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" @@ -807,6 +1081,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.2", +] + [[package]] name = "dirs" version = "6.0.0" @@ -875,7 +1159,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", "rfc6979", "serdect", @@ -915,7 +1199,7 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", @@ -985,12 +1269,44 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fastrand" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "ff" version = "0.13.1" @@ -1007,6 +1323,18 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.6", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1019,6 +1347,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.5.0" @@ -1055,6 +1389,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures-channel" version = "0.3.32" @@ -1191,7 +1531,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -1199,6 +1539,9 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "hashlink" @@ -1221,6 +1564,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "0.4.1" @@ -1233,7 +1585,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -1482,12 +1834,38 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "include_bytes_aligned" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + [[package]] name = "indexmap" version = "1.9.3" @@ -1526,6 +1904,15 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1586,6 +1973,41 @@ dependencies = [ "cpufeatures 0.2.17", ] +[[package]] +name = "keccak" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", +] + +[[package]] +name = "keccak-asm" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1766b89733097006f3a1388a02849865d6bc98c89273cb622e29fdd209922183" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + [[package]] name = "lazy-regex" version = "3.6.0" @@ -1702,7 +2124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", - "keccak", + "keccak 0.1.6", "rand_core 0.6.4", "zeroize", ] @@ -1860,6 +2282,34 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "paste" version = "1.0.15" @@ -1881,6 +2331,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -1954,6 +2414,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1990,11 +2461,16 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ + "bit-set", + "bit-vec", "bitflags 2.11.1", "num-traits", "rand 0.9.4", "rand_chacha 0.9.0", "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", "unarray", ] @@ -2021,6 +2497,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quinn" version = "0.11.9" @@ -2097,12 +2579,19 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ + "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] @@ -2164,6 +2653,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rapidhash" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +dependencies = [ + "rustversion", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -2307,7 +2805,7 @@ dependencies = [ "risc0-zkp", "risc0-zkvm-platform", "ruint", - "semver", + "semver 1.0.28", "serde", "tracing", ] @@ -2329,7 +2827,7 @@ dependencies = [ "risc0-zkp", "risc0-zkvm-platform", "rzup", - "semver", + "semver 1.0.28", "serde", "serde_json", "stability", @@ -2404,9 +2902,9 @@ dependencies = [ "anyhow", "ark-bn254", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-groth16", - "ark-serialize", + "ark-serialize 0.5.0", "bytemuck", "hex", "num-bigint", @@ -2438,7 +2936,7 @@ dependencies = [ "borsh", "bytemuck", "cfg-if", - "digest", + "digest 0.10.7", "hex", "hex-literal", "metal", @@ -2480,7 +2978,7 @@ dependencies = [ "risc0-zkvm-platform", "rrs-lib", "rzup", - "semver", + "semver 1.0.28", "serde", "sha2", "stability", @@ -2504,6 +3002,16 @@ dependencies = [ "stability", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "rrs-lib" version = "0.1.0" @@ -2521,7 +3029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid", - "digest", + "digest 0.10.7", "num-bigint-dig", "num-integer", "num-traits", @@ -2536,14 +3044,27 @@ dependencies = [ [[package]] name = "ruint" -version = "1.18.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "ark-ff 0.5.0", "borsh", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", "proptest", "rand 0.8.6", "rand 0.9.4", + "rlp", "ruint-macro", "serde_core", "valuable", @@ -2562,13 +3083,28 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.28", ] [[package]] @@ -2625,6 +3161,18 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.23" @@ -2639,7 +3187,7 @@ checksum = "5d2aed296f203fa64bcb4b52069356dd86d6ec578593985b919b6995bee1f0ae" dependencies = [ "hex", "rsa", - "semver", + "semver 1.0.28", "serde", "serde_with", "sha2", @@ -2689,6 +3237,35 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3c81b43dc2d8877c216a3fccf76677ee1ebccd429566d3e67447290d0c42b2" +dependencies = [ + "bitcoin_hashes", + "rand 0.9.4", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb913707158fadaf0d8702c2db0e857de66eb003ccfdda5924b5f5ac98efb38" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.28" @@ -2699,6 +3276,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.228" @@ -2813,7 +3399,27 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures 0.2.17", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" +dependencies = [ + "digest 0.11.3", + "keccak 0.2.0", +] + +[[package]] +name = "sha3-asm" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3f15d4e239ebe08413eed880e0f9b5af4b40ee0472543320efa91d488e96a7" +dependencies = [ + "cc", + "cfg-if", ] [[package]] @@ -2828,7 +3434,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -2962,6 +3568,12 @@ dependencies = [ "token_core", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.1" @@ -3037,6 +3649,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.27.0" @@ -3361,11 +3979,14 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" name = "twap_oracle_core" version = "0.1.0" dependencies = [ + "alloy-primitives", "borsh", "nssa_core", "risc0-zkvm", + "ruint", "serde", "spel-framework-macros", + "uniswap_v3_math", ] [[package]] @@ -3374,6 +3995,24 @@ version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unarray" version = "0.1.4" @@ -3386,12 +4025,29 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "uniswap_v3_math" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e393498a831893ce69ed6e1d06615e400bd1e8f97e9fcd113324f2d610fe6d45" +dependencies = [ + "alloy-primitives", + "eyre", + "thiserror 2.0.18", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -3428,6 +4084,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "want" version = "0.3.1" @@ -3560,7 +4225,7 @@ dependencies = [ "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap 2.14.0", - "semver", + "semver 1.0.28", ] [[package]] @@ -3911,7 +4576,7 @@ dependencies = [ "id-arena", "indexmap 2.14.0", "log", - "semver", + "semver 1.0.28", "serde", "serde_derive", "serde_json", @@ -3925,6 +4590,15 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "yaml-rust2" version = "0.10.4" diff --git a/programs/twap_oracle/core/Cargo.toml b/programs/twap_oracle/core/Cargo.toml index c49d18e..55166ac 100644 --- a/programs/twap_oracle/core/Cargo.toml +++ b/programs/twap_oracle/core/Cargo.toml @@ -12,3 +12,9 @@ borsh = { version = "1.5", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } spel-framework-macros = { git = "https://github.com/logos-co/spel.git", tag = "v0.3.0", package = "spel-framework-macros" } risc0-zkvm = { version = "=3.0.5", default-features = false } +uniswap_v3_math = "0.6.2" +alloy-primitives = { version = "1", default-features = false } +# Pin ruint (transitive via alloy-primitives) below 1.18, which raised its MSRV to rustc 1.90. +# The risc0 guest toolchain ships rustc 1.88, so 1.18+ fails the guest build. 1.17.0 (MSRV 1.85) +# is the newest compatible release. Remove this pin once the risc0 toolchain advances past 1.90. +ruint = { version = "=1.17.0", default-features = false } diff --git a/programs/twap_oracle/core/src/lib.rs b/programs/twap_oracle/core/src/lib.rs index 72510ac..b12e389 100644 --- a/programs/twap_oracle/core/src/lib.rs +++ b/programs/twap_oracle/core/src/lib.rs @@ -82,6 +82,30 @@ pub enum Instruction { /// New raw tick from the price source. tick: i32, }, + /// Computes the TWAP over `window_duration` from the [`PriceObservations`] ring buffer and + /// writes the result to the [`OraclePriceAccount`]. + /// + /// Permissionless — anyone may call this. Returns all accounts unchanged (no-op) if the + /// ring buffer holds fewer than two observations. Once at least two observations exist the + /// TWAP is computed over the available history, which may be shorter than `window_duration` + /// while the buffer is young. + /// + /// The resulting TWAP tick is stored in [`OraclePriceAccount::price`] via + /// [`tick_to_oracle_price`]. Consumers decode with [`oracle_price_to_tick`]. + /// + /// Required accounts (in order): + /// 1. Price observations account — initialized PDA derived from + /// `compute_price_observations_pda(self_program_id, price_source_id, window_duration)`. + /// 2. Oracle price account — initialized PDA derived from + /// `compute_oracle_price_account_pda(self_program_id, price_source_id, window_duration)`. + /// 3. Clock account — read-only; supplies the publication timestamp. + PublishPrice { + /// ID of the price source; used to verify both PDAs. + price_source_id: AccountId, + /// Duration of the TWAP window in milliseconds; used to verify both PDAs and to + /// locate the boundary observation in the ring buffer. + window_duration: u64, + }, /// Records the current tick from a [`CurrentTickAccount`] into a [`PriceObservations`] /// ring buffer. /// @@ -328,6 +352,53 @@ impl From<&OraclePriceAccount> for Data { } } +// ────────────────────────────────────────────────────────────────────────────── +// TWAP price encoding +// ────────────────────────────────────────────────────────────────────────────── + +/// Number of fractional bits in the [`OraclePriceAccount::price`] fixed-point value. +/// +/// The price is stored as a `Q64.64` ratio: `OraclePriceAccount::price / 2^PRICE_FRACTIONAL_BITS` +/// is the amount of `quote_asset` one unit of `base_asset` is worth. A consumer multiplies a +/// token amount by the price with `(amount * price) >> PRICE_FRACTIONAL_BITS`. +pub const PRICE_FRACTIONAL_BITS: u32 = 64; + +/// Converts a TWAP tick into the `Q64.64` fixed-point price stored in +/// [`OraclePriceAccount::price`]. +/// +/// The price is `1.0001^tick`, computed via the Uniswap v3 `sqrtPriceX96` representation +/// (pure-integer, no floating point) and then squared back to a plain ratio: +/// +/// ```text +/// sqrtPriceX96 = sqrt(1.0001^tick) * 2^96 +/// price = sqrtPriceX96^2 / 2^128 = 1.0001^tick * 2^64 (Q64.64) +/// ``` +/// +/// `sqrtPriceX96^2` is computed with [`full_math::mul_div`] using a 512-bit intermediate, so it +/// never overflows for any valid tick. The tick is clamped to `[MIN_TICK, MAX_TICK]` and the +/// result saturates at `u128::MAX` for the (practically unreachable) ticks above ~443 636 whose +/// ratio would exceed `2^64`. +/// +/// See `docs/twap-oracle-tick-to-price-conversion.md` for the full derivation. +#[must_use] +pub fn tick_to_oracle_price(tick: i32) -> u128 { + use alloy_primitives::U256; + use uniswap_v3_math::tick_math::{MAX_TICK, MIN_TICK}; + + // 2^128, used to bring sqrtPriceX96^2 (a Q128.128 square) down to Q64.64. + // Built from limbs (little-endian u64 words) to avoid arithmetic operators on U256. + const TWO_POW_128: U256 = U256::from_limbs([0, 0, 1, 0]); + + let clamped_tick = tick.clamp(MIN_TICK, MAX_TICK); + let sqrt_price_x96 = uniswap_v3_math::tick_math::get_sqrt_ratio_at_tick(clamped_tick) + .expect("clamped tick is within [MIN_TICK, MAX_TICK]"); + let price_q64_64 = + uniswap_v3_math::full_math::mul_div(sqrt_price_x96, sqrt_price_x96, TWO_POW_128) + .expect("1.0001^tick * 2^64 fits in U256 for any valid tick"); + + u128::try_from(price_q64_64).unwrap_or(u128::MAX) +} + // ────────────────────────────────────────────────────────────────────────────── // Current tick account // ────────────────────────────────────────────────────────────────────────────── @@ -401,3 +472,74 @@ pub fn compute_current_tick_account_pda_seed(price_source_id: AccountId) -> PdaS .expect("Hash output must be exactly 32 bytes long"), ) } + +#[cfg(test)] +mod tests { + use super::*; + + /// `1.0` in Q64.64 is `2^64`. + const ONE_Q64_64: u128 = 1u128 << PRICE_FRACTIONAL_BITS; + + #[test] + fn tick_zero_is_unit_price() { + // 1.0001^0 = 1.0 → exactly 2^64 in Q64.64. + assert_eq!(tick_to_oracle_price(0), ONE_Q64_64); + } + + #[test] + fn positive_tick_is_above_unit() { + assert!(tick_to_oracle_price(1) > ONE_Q64_64); + assert!(tick_to_oracle_price(10_000) > ONE_Q64_64); + } + + #[test] + fn negative_tick_is_below_unit() { + assert!(tick_to_oracle_price(-1) < ONE_Q64_64); + assert!(tick_to_oracle_price(-10_000) < ONE_Q64_64); + } + + #[test] + fn price_is_monotonic_in_tick() { + let mut prev = tick_to_oracle_price(-50_000); + for tick in (-49_000..=50_000).step_by(1_000) { + let cur = tick_to_oracle_price(tick); + assert!(cur > prev, "price must increase with tick at {tick}"); + prev = cur; + } + } + + #[test] + fn tick_10000_matches_known_ratio() { + // 1.0001^10000 ≈ 2.71814. Check the ratio in milli-units (× 1000) lands in [2717, 2719] + // using integer math only — `price * 1000 / 2^64` ≈ 2718. + let price = tick_to_oracle_price(10_000); + let ratio_milli = price + .checked_mul(1_000) + .and_then(|scaled| scaled.checked_div(ONE_Q64_64)) + .expect("price * 1000 fits in u128"); + assert!( + (2_717..=2_719).contains(&ratio_milli), + "got {ratio_milli} / 1000" + ); + } + + #[test] + fn extreme_positive_tick_saturates() { + // 1.0001^MAX_TICK far exceeds 2^64, so the Q64.64 value saturates at u128::MAX. + let price = tick_to_oracle_price(uniswap_v3_math::tick_math::MAX_TICK); + assert_eq!(price, u128::MAX); + } + + #[test] + fn ticks_beyond_bounds_are_clamped() { + // Ticks outside [MIN_TICK, MAX_TICK] must not panic; they clamp to the bound. + assert_eq!( + tick_to_oracle_price(i32::MAX), + tick_to_oracle_price(uniswap_v3_math::tick_math::MAX_TICK) + ); + assert_eq!( + tick_to_oracle_price(i32::MIN), + tick_to_oracle_price(uniswap_v3_math::tick_math::MIN_TICK) + ); + } +} diff --git a/programs/twap_oracle/methods/guest/Cargo.lock b/programs/twap_oracle/methods/guest/Cargo.lock index 591ae6f..3bbeb85 100644 --- a/programs/twap_oracle/methods/guest/Cargo.lock +++ b/programs/twap_oracle/methods/guest/Cargo.lock @@ -29,6 +29,44 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy-primitives" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4885c1409b6936c4898e646ef58baf6ec54edaf6d8179f79df805a7b85b7cf3e" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "foldhash 0.2.0", + "hashbrown 0.17.1", + "indexmap 2.14.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.9.4", + "rapidhash", + "ruint", + "rustc-hash", + "secp256k1", + "serde", + "sha3", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" +dependencies = [ + "arrayvec", + "bytes", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -51,9 +89,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" dependencies = [ "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-r1cs-std", - "ark-std", + "ark-std 0.5.0", ] [[package]] @@ -65,14 +103,14 @@ dependencies = [ "ahash", "ark-crypto-primitives-macros", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-serialize", + "ark-serialize 0.5.0", "ark-snark", - "ark-std", + "ark-std 0.5.0", "blake2", "derivative", - "digest", + "digest 0.10.7", "fnv", "merlin", "sha2", @@ -96,10 +134,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" dependencies = [ "ahash", - "ark-ff", + "ark-ff 0.5.0", "ark-poly", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "educe", "fnv", "hashbrown 0.15.5", @@ -110,18 +148,56 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + [[package]] name = "ark-ff" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "arrayvec", - "digest", + "digest 0.10.7", "educe", "itertools 0.13.0", "num-bigint", @@ -130,6 +206,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-asm" version = "0.5.0" @@ -140,6 +236,31 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-macros" version = "0.5.0" @@ -161,11 +282,11 @@ checksum = "88f1d0f3a534bb54188b8dcc104307db6c56cdae574ddc3212aec0625740fc7e" dependencies = [ "ark-crypto-primitives", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-poly", "ark-relations", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", ] [[package]] @@ -175,9 +296,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" dependencies = [ "ahash", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "educe", "fnv", "hashbrown 0.15.5", @@ -190,9 +311,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" dependencies = [ "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-std", + "ark-std 0.5.0", "educe", "num-bigint", "num-integer", @@ -206,12 +327,33 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" dependencies = [ - "ark-ff", - "ark-std", + "ark-ff 0.5.0", + "ark-std 0.5.0", "tracing", "tracing-subscriber", ] +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + [[package]] name = "ark-serialize" version = "0.5.0" @@ -219,9 +361,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ "ark-serialize-derive", - "ark-std", + "ark-std 0.5.0", "arrayvec", - "digest", + "digest 0.10.7", "num-bigint", ] @@ -242,10 +384,30 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d368e2848c2d4c129ce7679a7d0d2d612b6a274d3ea6a13bad4445d61b381b88" dependencies = [ - "ark-ff", + "ark-ff 0.5.0", "ark-relations", - "ark-serialize", - "ark-std", + "ark-serialize 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.6", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.6", ] [[package]] @@ -276,6 +438,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "autocfg" version = "1.5.1" @@ -315,12 +488,37 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + [[package]] name = "bit-vec" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitcoin-io" +version = "0.1.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11301df0b06f22dea7bb1916403fdd88a371031e495c49b8f96931b28189e175" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9901a56e133a1fc86eeb1113e2591f45f4682451ca893bff494d2f88918e3f" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -333,13 +531,25 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -418,6 +628,12 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + [[package]] name = "bytemuck" version = "1.25.0" @@ -488,7 +704,7 @@ checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.28", "serde", "serde_json", "thiserror 2.0.18", @@ -568,12 +784,54 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "const-hex" +version = "1.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e2a781ebdf4467d1428dc4593067825fb646f6871475098d8577421af73558" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "proptest", + "serde_core", +] + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_format" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -619,6 +877,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -797,13 +1061,23 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.1", "syn 2.0.117", "unicode-xid", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" @@ -816,6 +1090,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.2", +] + [[package]] name = "dirs" version = "6.0.0" @@ -834,7 +1118,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -884,7 +1168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", "rfc6979", "serdect", @@ -924,7 +1208,7 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", @@ -991,7 +1275,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", ] [[package]] @@ -1000,6 +1294,28 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "ff" version = "0.13.1" @@ -1016,6 +1332,18 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.6", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1028,6 +1356,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.5.0" @@ -1064,6 +1398,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures-channel" version = "0.3.32" @@ -1200,7 +1540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -1208,6 +1548,9 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "hashlink" @@ -1230,6 +1573,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "0.4.1" @@ -1242,7 +1594,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -1491,12 +1843,38 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "include_bytes_aligned" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + [[package]] name = "indexmap" version = "1.9.3" @@ -1535,6 +1913,15 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1595,6 +1982,41 @@ dependencies = [ "cpufeatures 0.2.17", ] +[[package]] +name = "keccak" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", +] + +[[package]] +name = "keccak-asm" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1766b89733097006f3a1388a02849865d6bc98c89273cb622e29fdd209922183" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + [[package]] name = "lazy-regex" version = "3.6.0" @@ -1711,7 +2133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", - "keccak", + "keccak 0.1.6", "rand_core 0.6.4", "zeroize", ] @@ -1869,6 +2291,34 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "paste" version = "1.0.15" @@ -1890,6 +2340,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -1963,6 +2423,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1999,11 +2470,16 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ + "bit-set", + "bit-vec", "bitflags 2.11.1", "num-traits", "rand 0.9.4", "rand_chacha 0.9.0", "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", "unarray", ] @@ -2030,6 +2506,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quinn" version = "0.11.9" @@ -2106,12 +2588,19 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ + "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] @@ -2173,6 +2662,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rapidhash" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +dependencies = [ + "rustversion", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -2316,7 +2814,7 @@ dependencies = [ "risc0-zkp", "risc0-zkvm-platform", "ruint", - "semver", + "semver 1.0.28", "serde", "tracing", ] @@ -2338,7 +2836,7 @@ dependencies = [ "risc0-zkp", "risc0-zkvm-platform", "rzup", - "semver", + "semver 1.0.28", "serde", "serde_json", "stability", @@ -2413,9 +2911,9 @@ dependencies = [ "anyhow", "ark-bn254", "ark-ec", - "ark-ff", + "ark-ff 0.5.0", "ark-groth16", - "ark-serialize", + "ark-serialize 0.5.0", "bytemuck", "hex", "num-bigint", @@ -2447,7 +2945,7 @@ dependencies = [ "borsh", "bytemuck", "cfg-if", - "digest", + "digest 0.10.7", "hex", "hex-literal", "metal", @@ -2489,7 +2987,7 @@ dependencies = [ "risc0-zkvm-platform", "rrs-lib", "rzup", - "semver", + "semver 1.0.28", "serde", "sha2", "stability", @@ -2513,6 +3011,16 @@ dependencies = [ "stability", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "rrs-lib" version = "0.1.0" @@ -2530,7 +3038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid", - "digest", + "digest 0.10.7", "num-bigint-dig", "num-integer", "num-traits", @@ -2545,14 +3053,27 @@ dependencies = [ [[package]] name = "ruint" -version = "1.18.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "ark-ff 0.5.0", "borsh", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", "proptest", "rand 0.8.6", "rand 0.9.4", + "rlp", "ruint-macro", "serde_core", "valuable", @@ -2571,13 +3092,28 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.28", ] [[package]] @@ -2590,7 +3126,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -2634,6 +3170,18 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.23" @@ -2648,7 +3196,7 @@ checksum = "5d2aed296f203fa64bcb4b52069356dd86d6ec578593985b919b6995bee1f0ae" dependencies = [ "hex", "rsa", - "semver", + "semver 1.0.28", "serde", "serde_with", "sha2", @@ -2698,6 +3246,35 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3c81b43dc2d8877c216a3fccf76677ee1ebccd429566d3e67447290d0c42b2" +dependencies = [ + "bitcoin_hashes", + "rand 0.9.4", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb913707158fadaf0d8702c2db0e857de66eb003ccfdda5924b5f5ac98efb38" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.28" @@ -2708,6 +3285,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.228" @@ -2822,7 +3408,27 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures 0.2.17", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" +dependencies = [ + "digest 0.11.3", + "keccak 0.2.0", +] + +[[package]] +name = "sha3-asm" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3f15d4e239ebe08413eed880e0f9b5af4b40ee0472543320efa91d488e96a7" +dependencies = [ + "cc", + "cfg-if", ] [[package]] @@ -2837,7 +3443,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -2860,7 +3466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -2935,6 +3541,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.1" @@ -3010,6 +3622,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.27.0" @@ -3020,7 +3638,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3338,11 +3956,14 @@ dependencies = [ name = "twap_oracle_core" version = "0.1.0" dependencies = [ + "alloy-primitives", "borsh", "nssa_core", "risc0-zkvm", + "ruint", "serde", "spel-framework-macros", + "uniswap_v3_math", ] [[package]] @@ -3360,6 +3981,24 @@ version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unarray" version = "0.1.4" @@ -3372,12 +4011,29 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "uniswap_v3_math" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e393498a831893ce69ed6e1d06615e400bd1e8f97e9fcd113324f2d610fe6d45" +dependencies = [ + "alloy-primitives", + "eyre", + "thiserror 2.0.18", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -3414,6 +4070,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "want" version = "0.3.1" @@ -3546,7 +4211,7 @@ dependencies = [ "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap 2.14.0", - "semver", + "semver 1.0.28", ] [[package]] @@ -3897,7 +4562,7 @@ dependencies = [ "id-arena", "indexmap 2.14.0", "log", - "semver", + "semver 1.0.28", "serde", "serde_derive", "serde_json", @@ -3911,6 +4576,15 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "yaml-rust2" version = "0.10.4" diff --git a/programs/twap_oracle/methods/guest/src/bin/twap_oracle.rs b/programs/twap_oracle/methods/guest/src/bin/twap_oracle.rs index bdbe644..4c7075e 100644 --- a/programs/twap_oracle/methods/guest/src/bin/twap_oracle.rs +++ b/programs/twap_oracle/methods/guest/src/bin/twap_oracle.rs @@ -94,6 +94,33 @@ mod twap_oracle { Ok(spel_framework::SpelOutput::execute(post_states, vec![])) } + /// Computes the TWAP from the price observations ring buffer and writes it to the price + /// account. + /// + /// Expected accounts: + /// 1. `price_observations` — initialized PDA owned by this oracle program. + /// 2. `oracle_price_account` — initialized PDA owned by this oracle program. + /// 3. `clock` — read-only LEZ clock account. + #[instruction] + pub fn publish_price( + ctx: ProgramContext, + price_observations: AccountWithMetadata, + oracle_price_account: AccountWithMetadata, + clock: AccountWithMetadata, + price_source_id: AccountId, + window_duration: u64, + ) -> SpelResult { + let post_states = twap_oracle_program::publish_price::publish_price( + price_observations, + oracle_price_account, + clock, + price_source_id, + window_duration, + ctx.self_program_id, + ); + Ok(spel_framework::SpelOutput::execute(post_states, vec![])) + } + /// Records the current tick into a price observations ring buffer. /// /// Expected accounts: diff --git a/programs/twap_oracle/src/lib.rs b/programs/twap_oracle/src/lib.rs index a01c5fe..9f7e825 100644 --- a/programs/twap_oracle/src/lib.rs +++ b/programs/twap_oracle/src/lib.rs @@ -5,5 +5,6 @@ pub use twap_oracle_core as core; pub mod create_current_tick_account; pub mod create_oracle_price_account; pub mod create_price_observations; +pub mod publish_price; pub mod record_tick; pub mod update_current_tick; diff --git a/programs/twap_oracle/src/publish_price.rs b/programs/twap_oracle/src/publish_price.rs new file mode 100644 index 0000000..504dbfe --- /dev/null +++ b/programs/twap_oracle/src/publish_price.rs @@ -0,0 +1,510 @@ +use clock_core::ClockAccountData; +use nssa_core::{ + account::{AccountId, AccountWithMetadata, Data}, + program::{AccountPostState, ProgramId}, +}; +use twap_oracle_core::{ + compute_oracle_price_account_pda, compute_price_observations_pda, tick_to_oracle_price, + OraclePriceAccount, PriceObservations, OBSERVATIONS_CAPACITY, +}; + +/// Computes the TWAP over the full span of the [`PriceObservations`] ring buffer and writes +/// the result to the [`OraclePriceAccount`]. +/// +/// Each observations account is calibrated to a specific `window_duration` via its sampling +/// guard (`min_interval = window_duration / OBSERVATIONS_CAPACITY`), so the oldest valid entry +/// is always the natural start of the window — no boundary search is needed. +/// +/// Returns all accounts unchanged when fewer than two observations are available. The price +/// account stays at `timestamp = 0` (uninitialized signal) until there is something to publish. +/// +/// # Panics +/// Panics if: +/// - `price_observations.account_id` does not match +/// `compute_price_observations_pda(oracle_program_id, price_source_id, window_duration)`. +/// - `oracle_price_account.account_id` does not match +/// `compute_oracle_price_account_pda(oracle_program_id, price_source_id, window_duration)`. +/// - Either account is not a valid initialised account of its respective type. +pub fn publish_price( + price_observations: AccountWithMetadata, + oracle_price_account: AccountWithMetadata, + clock: AccountWithMetadata, + price_source_id: AccountId, + window_duration: u64, + oracle_program_id: ProgramId, +) -> Vec { + assert_eq!( + price_observations.account_id, + compute_price_observations_pda(oracle_program_id, price_source_id, window_duration), + "PublishPrice: price observations account ID does not match expected PDA" + ); + assert_eq!( + oracle_price_account.account_id, + compute_oracle_price_account_pda(oracle_program_id, price_source_id, window_duration), + "PublishPrice: oracle price account ID does not match expected PDA" + ); + + let clock_data = ClockAccountData::from_bytes(clock.account.data.as_ref()); + let now = clock_data.timestamp; + + let observations = PriceObservations::try_from(&price_observations.account.data) + .expect("PublishPrice: price observations account must be initialized"); + let mut price_account = OraclePriceAccount::try_from(&oracle_price_account.account.data) + .expect("PublishPrice: oracle price account must be initialized"); + + // No-op: need at least two observations to compute a TWAP. + if observations.total_entries < 2 { + return vec![ + AccountPostState::new(price_observations.account.clone()), + AccountPostState::new(oracle_price_account.account.clone()), + AccountPostState::new(clock.account.clone()), + ]; + } + + let capacity = + usize::try_from(OBSERVATIONS_CAPACITY).expect("OBSERVATIONS_CAPACITY fits in usize"); + + // t2: the most recent observation. + let t2_index = if observations.write_index == 0 { + capacity + .checked_sub(1) + .expect("OBSERVATIONS_CAPACITY is non-zero") + } else { + usize::try_from( + observations + .write_index + .checked_sub(1) + .expect("write_index > 0"), + ) + .expect("write_index - 1 fits in usize") + }; + + // t1: the oldest valid observation. Once the buffer is full, the oldest entry sits at + // write_index (the slot about to be overwritten next). Before that, entries start at 0. + let is_full = observations.total_entries >= u64::from(OBSERVATIONS_CAPACITY); + let t1_index = if is_full { + usize::try_from(observations.write_index).expect("write_index fits in usize") + } else { + 0 + }; + + let t1 = observations + .entries + .get(t1_index) + .expect("t1_index is within bounds"); + let t2 = observations + .entries + .get(t2_index) + .expect("t2_index is within bounds"); + + let elapsed_ms = t2 + .timestamp + .checked_sub(t1.timestamp) + .expect("t2.timestamp >= t1.timestamp"); + let cumulative_diff = t2 + .tick_cumulative + .checked_sub(t1.tick_cumulative) + .expect("tick_cumulative difference fits in i64"); + let elapsed_ms_i64 = i64::try_from(elapsed_ms).expect("elapsed_ms fits in i64"); + let twap_tick_i64 = cumulative_diff + .checked_div(elapsed_ms_i64) + .expect("elapsed_ms is non-zero"); + let twap_tick = i32::try_from(twap_tick_i64).expect("TWAP tick fits in i32"); + + price_account.price = tick_to_oracle_price(twap_tick); + price_account.timestamp = now; + + let mut oracle_price_account_post = oracle_price_account.account.clone(); + oracle_price_account_post.data = Data::from(&price_account); + + vec![ + AccountPostState::new(price_observations.account.clone()), + AccountPostState::new(oracle_price_account_post), + AccountPostState::new(clock.account.clone()), + ] +} + +#[cfg(test)] +mod tests { + use nssa_core::account::{Account, AccountId, Nonce}; + use twap_oracle_core::{ + compute_oracle_price_account_pda, compute_price_observations_pda, tick_to_oracle_price, + ObservationEntry, OraclePriceAccount, PriceObservations, OBSERVATIONS_CAPACITY, + }; + + use super::*; + + const ORACLE_PROGRAM_ID: ProgramId = [77u32; 8]; + const CLOCK_PROGRAM_ID: ProgramId = [88u32; 8]; + const WINDOW_24H: u64 = 24 * 60 * 60 * 1_000; + + fn price_source_id() -> AccountId { + AccountId::new([1u8; 32]) + } + fn base_asset_id() -> AccountId { + AccountId::new([10u8; 32]) + } + fn quote_asset_id() -> AccountId { + AccountId::new([11u8; 32]) + } + + fn clock_account_with_timestamp(timestamp: u64) -> AccountWithMetadata { + let data = ClockAccountData { + block_id: 0, + timestamp, + } + .to_bytes(); + AccountWithMetadata { + account: Account { + program_owner: CLOCK_PROGRAM_ID, + balance: 0, + data: Data::try_from(data).expect("ClockAccountData fits in Data"), + nonce: Nonce(0), + }, + is_authorized: false, + account_id: AccountId::new([99u8; 32]), + } + } + + /// Builds a [`PriceObservations`] from `(timestamp_ms, tick_cumulative)` pairs written in + /// order starting at index 0. `write_index` is set to `entries_data.len()`. + fn make_price_observations( + entries_data: &[(u64, i64)], + last_recorded_tick: i32, + ) -> AccountWithMetadata { + let capacity = + usize::try_from(OBSERVATIONS_CAPACITY).expect("OBSERVATIONS_CAPACITY fits in usize"); + let mut entries = vec![ObservationEntry::default(); capacity]; + for (i, &(timestamp, tick_cumulative)) in entries_data.iter().enumerate() { + *entries.get_mut(i).expect("i < capacity") = ObservationEntry { + timestamp, + tick_cumulative, + }; + } + let write_index = u32::try_from(entries_data.len()).expect("entry count fits in u32"); + let total_entries = u64::try_from(entries_data.len()).expect("entry count fits in u64"); + let obs = PriceObservations { + price_source_id: price_source_id(), + write_index, + total_entries, + last_recorded_tick, + entries, + }; + AccountWithMetadata { + account: Account { + program_owner: ORACLE_PROGRAM_ID, + balance: 0, + data: Data::from(&obs), + nonce: Nonce(0), + }, + is_authorized: false, + account_id: compute_price_observations_pda( + ORACLE_PROGRAM_ID, + price_source_id(), + WINDOW_24H, + ), + } + } + + fn make_oracle_price_account() -> AccountWithMetadata { + let account = OraclePriceAccount { + base_asset: base_asset_id(), + quote_asset: quote_asset_id(), + price: 0, + timestamp: 0, + source_id: price_source_id(), + confidence_interval: 0, + }; + AccountWithMetadata { + account: Account { + program_owner: ORACLE_PROGRAM_ID, + balance: 0, + data: Data::from(&account), + nonce: Nonce(0), + }, + is_authorized: false, + account_id: compute_oracle_price_account_pda( + ORACLE_PROGRAM_ID, + price_source_id(), + WINDOW_24H, + ), + } + } + + // ── happy path ──────────────────────────────────────────────────────────── + + #[test] + fn returns_three_post_states() { + let post_states = publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0), + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + assert_eq!(post_states.len(), 3); + } + + #[test] + fn twap_tick_computed_and_stored_as_price() { + // Constant tick = 100 over 24 h → twap = 100 + let cumulative = 100_i64 + .checked_mul(i64::try_from(WINDOW_24H).expect("fits")) + .expect("100 * WINDOW_24H fits in i64"); + let post_states = publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, cumulative)], 100), + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + let account = OraclePriceAccount::try_from(&post_states[1].account().data) + .expect("valid OraclePriceAccount"); + assert_eq!(account.price, tick_to_oracle_price(100)); + } + + #[test] + fn negative_twap_tick_stored_correctly() { + // Constant tick = -50 over 24 h → twap = -50 + let cumulative = (-50_i64) + .checked_mul(i64::try_from(WINDOW_24H).expect("fits")) + .expect("-50 * WINDOW_24H fits in i64"); + let post_states = publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, cumulative)], -50), + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + let account = OraclePriceAccount::try_from(&post_states[1].account().data) + .expect("valid OraclePriceAccount"); + assert_eq!(account.price, tick_to_oracle_price(-50)); + } + + #[test] + fn zero_twap_tick_stored_correctly() { + let post_states = publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0), + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + let account = OraclePriceAccount::try_from(&post_states[1].account().data) + .expect("valid OraclePriceAccount"); + assert_eq!(account.price, tick_to_oracle_price(0)); + } + + #[test] + fn timestamp_set_to_clock_now() { + let now = WINDOW_24H + .checked_mul(2) + .expect("WINDOW_24H * 2 fits in u64"); + let post_states = publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0), + make_oracle_price_account(), + clock_account_with_timestamp(now), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + let account = OraclePriceAccount::try_from(&post_states[1].account().data) + .expect("valid OraclePriceAccount"); + assert_eq!(account.timestamp, now); + } + + #[test] + fn other_price_account_fields_preserved() { + let post_states = publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0), + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + let account = OraclePriceAccount::try_from(&post_states[1].account().data) + .expect("valid OraclePriceAccount"); + assert_eq!(account.base_asset, base_asset_id()); + assert_eq!(account.quote_asset, quote_asset_id()); + assert_eq!(account.source_id, price_source_id()); + assert_eq!(account.confidence_interval, 0); + } + + #[test] + fn price_observations_account_is_not_modified() { + let observations = make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0); + let post_states = publish_price( + observations.clone(), + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + assert_eq!(*post_states[0].account(), observations.account); + } + + #[test] + fn clock_account_is_not_modified() { + let clock = clock_account_with_timestamp(WINDOW_24H); + let post_states = publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0), + make_oracle_price_account(), + clock.clone(), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + assert_eq!(*post_states[2].account(), clock.account); + } + + #[test] + fn twap_uses_oldest_and_newest_entries() { + // Three observations: tick 0 for first half, tick 200 for second half. + // t1 = entry[0] (oldest), t2 = entry[2] (newest). + // Average over full span = (0 * half + 200 * half) / full = 100. + let half = WINDOW_24H.checked_div(2).expect("fits"); + let half_i64 = i64::try_from(half).expect("fits"); + let full_i64 = i64::try_from(WINDOW_24H).expect("fits"); + // entry[0]: t=0, cumulative=0 (tick was 0 before this) + // entry[1]: t=half, cumulative=0 (tick=0 held from 0..half, so 0*half=0) + // entry[2]: t=WINDOW_24H, cumulative=200*half (tick=200 held from half..full) + let cumulative_at_half = 0_i64; + let cumulative_at_full = 200_i64.checked_mul(half_i64).expect("fits"); + let post_states = publish_price( + make_price_observations( + &[ + (0, 0), + (half, cumulative_at_half), + (WINDOW_24H, cumulative_at_full), + ], + 200, + ), + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + let account = OraclePriceAccount::try_from(&post_states[1].account().data) + .expect("valid OraclePriceAccount"); + // twap = (cumulative_at_full - 0) / (WINDOW_24H - 0) = 200*half / full = 200/2 = 100 + let expected_tick = cumulative_at_full.checked_div(full_i64).expect("non-zero"); + assert_eq!( + account.price, + tick_to_oracle_price(i32::try_from(expected_tick).expect("tick fits in i32")) + ); + } + + // ── no-op: insufficient history ─────────────────────────────────────────── + + #[test] + fn noop_when_only_one_observation() { + let initial = make_oracle_price_account(); + let post_states = publish_price( + make_price_observations(&[(0, 0)], 0), + initial.clone(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + assert_eq!(*post_states[1].account(), initial.account); + } + + #[test] + fn noop_leaves_price_account_timestamp_at_zero() { + let post_states = publish_price( + make_price_observations(&[(0, 0)], 0), + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + let account = OraclePriceAccount::try_from(&post_states[1].account().data) + .expect("valid OraclePriceAccount"); + assert_eq!(account.timestamp, 0); + } + + // ── precondition violations ─────────────────────────────────────────────── + + #[test] + #[should_panic(expected = "price observations account ID does not match expected PDA")] + fn wrong_price_observations_id_panics() { + let mut wrong = make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0); + wrong.account_id = AccountId::new([0u8; 32]); + publish_price( + wrong, + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + } + + #[test] + #[should_panic(expected = "oracle price account ID does not match expected PDA")] + fn wrong_oracle_price_account_id_panics() { + let mut wrong = make_oracle_price_account(); + wrong.account_id = AccountId::new([0u8; 32]); + publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0), + wrong, + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + } + + #[test] + #[should_panic(expected = "price observations account must be initialized")] + fn uninitialized_price_observations_panics() { + let uninit = AccountWithMetadata { + account: Account::default(), + is_authorized: false, + account_id: compute_price_observations_pda( + ORACLE_PROGRAM_ID, + price_source_id(), + WINDOW_24H, + ), + }; + publish_price( + uninit, + make_oracle_price_account(), + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + } + + #[test] + #[should_panic(expected = "oracle price account must be initialized")] + fn uninitialized_oracle_price_account_panics() { + let uninit = AccountWithMetadata { + account: Account::default(), + is_authorized: false, + account_id: compute_oracle_price_account_pda( + ORACLE_PROGRAM_ID, + price_source_id(), + WINDOW_24H, + ), + }; + publish_price( + make_price_observations(&[(0, 0), (WINDOW_24H, 0)], 0), + uninit, + clock_account_with_timestamp(WINDOW_24H), + price_source_id(), + WINDOW_24H, + ORACLE_PROGRAM_ID, + ); + } +}