From 3d8cd858dbd0e0035d6d4dd8e0caac83ca83be64 Mon Sep 17 00:00:00 2001 From: clabby Date: Sat, 6 Apr 2024 16:51:35 -0400 Subject: [PATCH] feat(preimage): `OracleServer` + `HintReader` Adds the host end of the `PreimageOracle` ABI plumbing. This includes two new traits: * `PreimageOracleServer` * `HintReaderServer` as well as implementations of both of them that compliment the existing client handles, the `OracleReader` and `HintWriter`. --- Cargo.lock | 553 +++++++++++++++++++++++++++++++++- crates/common/src/io.rs | 4 +- crates/preimage/Cargo.toml | 1 + crates/preimage/src/hint.rs | 108 ++++++- crates/preimage/src/key.rs | 28 +- crates/preimage/src/lib.rs | 6 +- crates/preimage/src/oracle.rs | 102 +++++-- crates/preimage/src/traits.rs | 32 +- 8 files changed, 792 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a96d113ed..c21e39ca9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,9 @@ dependencies = [ "hex-literal", "itoa", "k256", + "keccak-asm", + "proptest", + "rand", "ruint", "serde", "tiny-keccak", @@ -82,6 +85,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ "alloy-rlp-derive", + "arrayvec", "bytes", ] @@ -156,6 +160,136 @@ version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +[[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", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.0", + "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-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-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-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "async-trait" version = "0.1.77" @@ -167,6 +301,17 @@ dependencies = [ "syn 2.0.50", ] +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -194,6 +339,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bit-set" version = "0.5.3" @@ -221,6 +372,18 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +[[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 = "block-buffer" version = "0.10.4" @@ -230,6 +393,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.5.0" @@ -323,6 +498,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -332,10 +518,19 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.0", "syn 1.0.109", ] +[[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" @@ -361,12 +556,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", "rfc6979", "signature", + "spki", ] +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -375,10 +577,11 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", + "pkcs8", "rand_core", "sec1", "subtle", @@ -407,6 +610,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[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 = "ff" version = "0.13.0" @@ -417,12 +631,30 @@ dependencies = [ "subtle", ] +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "generic-array" version = "0.14.7" @@ -511,7 +743,27 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -524,6 +776,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -539,9 +800,20 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", + "once_cell", "sha2", ] +[[package]] +name = "keccak-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "kona-common" version = "0.0.1" @@ -575,6 +847,7 @@ dependencies = [ name = "kona-preimage" version = "0.0.1" dependencies = [ + "alloy-primitives", "anyhow", "cfg-if", "kona-common", @@ -651,6 +924,26 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.18" @@ -686,6 +979,32 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "parity-scale-codec" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -715,18 +1034,60 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pest" +version = "2.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + [[package]] name = "pin-project-lite" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[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 = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -795,6 +1156,12 @@ dependencies = [ "proc-macro2", ] +[[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.5" @@ -859,6 +1226,16 @@ dependencies = [ "subtle", ] +[[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 = "ruint" version = "1.11.1" @@ -866,8 +1243,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825" dependencies = [ "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", "proptest", "rand", + "rlp", "ruint-macro", "serde", "valuable", @@ -886,13 +1272,28 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.22", ] [[package]] @@ -941,16 +1342,35 @@ dependencies = [ "base16ct", "der", "generic-array", + "pkcs8", "subtle", "zeroize", ] +[[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.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.197" @@ -990,7 +1410,17 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha3-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +dependencies = [ + "cc", + "cfg-if", ] [[package]] @@ -1008,7 +1438,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", ] @@ -1046,6 +1476,22 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "subtle" version = "2.5.0" @@ -1086,6 +1532,12 @@ dependencies = [ "syn 2.0.50", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.10.0" @@ -1098,6 +1550,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1137,12 +1609,47 @@ dependencies = [ "syn 2.0.50", ] +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[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" @@ -1320,6 +1827,24 @@ version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "zerocopy" version = "0.7.32" @@ -1345,3 +1870,17 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] diff --git a/crates/common/src/io.rs b/crates/common/src/io.rs index 33922537b..96426a98e 100644 --- a/crates/common/src/io.rs +++ b/crates/common/src/io.rs @@ -78,8 +78,8 @@ mod native_io { .write(buf) .map_err(|e| anyhow!("Error writing to buffer to file descriptor: {e}"))?; - // Reset the cursor back to 0 for the reader. - file.seek(SeekFrom::Start(0)) + // Reset the cursor back to before the data we just wrote for the reader's consumption. + file.seek(SeekFrom::Current(-(buf.len() as i64))) .map_err(|e| anyhow!("Failed to reset file cursor to 0: {e}"))?; // forget the file descriptor so that the `Drop` impl doesn't close it. diff --git a/crates/preimage/Cargo.toml b/crates/preimage/Cargo.toml index 84d6edb62..ebd55f1e6 100644 --- a/crates/preimage/Cargo.toml +++ b/crates/preimage/Cargo.toml @@ -19,3 +19,4 @@ kona-common = { path = "../common", version = "0.0.1" } [dev-dependencies] tokio = { version = "1.36.0", features = ["full"] } tempfile = "3.10.0" +alloy-primitives = "0.7.0" diff --git a/crates/preimage/src/hint.rs b/crates/preimage/src/hint.rs index 99861339a..97ea3cb84 100644 --- a/crates/preimage/src/hint.rs +++ b/crates/preimage/src/hint.rs @@ -1,5 +1,5 @@ -use crate::{traits::HintWriterClient, PipeHandle}; -use alloc::vec; +use crate::{traits::HintWriterClient, HintReaderServer, PipeHandle}; +use alloc::{string::String, vec}; use anyhow::Result; /// A [HintWriter] is a high-level interface to the hint pipe. It provides a way to write hints to @@ -36,3 +36,107 @@ impl HintWriterClient for HintWriter { Ok(()) } } + +/// A [HintReader] is a router for hints sent by the [HintWriter] from the client program. It +/// provides a way for the host to prepare preimages for reading. +#[derive(Debug, Clone, Copy)] +pub struct HintReader { + pipe_handle: PipeHandle, +} + +impl HintReader { + /// Create a new [HintReader] from a [PipeHandle]. + pub fn new(pipe_handle: PipeHandle) -> Self { + Self { pipe_handle } + } +} + +impl HintReaderServer for HintReader { + fn next_hint(&self, mut route_hint: impl FnMut(String) -> Result<()>) -> Result<()> { + // Read the length of the raw hint payload. + let mut len_buf = [0u8; 4]; + self.pipe_handle.read_exact(&mut len_buf)?; + let len = u32::from_be_bytes(len_buf); + + // Read the raw hint payload. + let mut payload = vec![0u8; len as usize]; + self.pipe_handle.read_exact(payload.as_mut_slice())?; + + // Route the hint + if let Err(e) = route_hint( + String::from_utf8(payload) + .map_err(|e| anyhow::anyhow!("Failed to decode hint payload: {e}"))?, + ) { + // Write back on error to prevent blocking the client. + self.pipe_handle.write(&[0x00])?; + anyhow::bail!("Failed to handle hint: {e}"); + } + + // Write back an acknowledgement to the client to unblock their process. + self.pipe_handle.write(&[0x00])?; + + Ok(()) + } +} +#[cfg(test)] +mod test { + extern crate std; + + use super::*; + use alloc::vec::Vec; + use kona_common::FileDescriptor; + use std::{fs::File, os::fd::AsRawFd}; + use tempfile::tempfile; + + /// Test struct containing the [HintReader] and [HintWriter]. The [File]s are stored in this + /// struct so that they are not dropped until the end of the test. + #[derive(Debug)] + struct ClientAndHost { + hint_writer: HintWriter, + hint_reader: HintReader, + _read_file: File, + _write_file: File, + } + + /// Helper for creating a new [HintReader] and [HintWriter] for testing. The file channel is + /// over two temporary files. + fn client_and_host() -> ClientAndHost { + let (read_file, write_file) = (tempfile().unwrap(), tempfile().unwrap()); + let (read_fd, write_fd) = ( + FileDescriptor::Wildcard(read_file.as_raw_fd().try_into().unwrap()), + FileDescriptor::Wildcard(write_file.as_raw_fd().try_into().unwrap()), + ); + let client_handle = PipeHandle::new(read_fd, write_fd); + let host_handle = PipeHandle::new(write_fd, read_fd); + + let hint_writer = HintWriter::new(client_handle); + let hint_reader = HintReader::new(host_handle); + + ClientAndHost { hint_writer, hint_reader, _read_file: read_file, _write_file: write_file } + } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_hint_client_and_host() { + const MOCK_DATA: &str = "test-hint 0xfacade"; + + let sys = client_and_host(); + let (hint_writer, hint_reader) = (sys.hint_writer, sys.hint_reader); + + let client = tokio::task::spawn(async move { hint_writer.write(MOCK_DATA) }); + let host = tokio::task::spawn(async move { + let mut v = Vec::new(); + let route_hint = |hint: String| { + v.push(hint.clone()); + Ok(()) + }; + hint_reader.next_hint(route_hint).unwrap(); + + assert_eq!(v.len(), 1); + + v.remove(0) + }); + + let (_, h) = tokio::join!(client, host); + assert_eq!(h.unwrap(), MOCK_DATA); + } +} diff --git a/crates/preimage/src/key.rs b/crates/preimage/src/key.rs index 4c1e9a565..5c301365c 100644 --- a/crates/preimage/src/key.rs +++ b/crates/preimage/src/key.rs @@ -2,7 +2,7 @@ //! the preimage oracle. /// -#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)] #[repr(u8)] pub enum PreimageKeyType { /// Local key types are local to a given instance of a fault-proof and context dependent. @@ -23,6 +23,21 @@ pub enum PreimageKeyType { Blob = 5, } +impl TryFrom for PreimageKeyType { + type Error = anyhow::Error; + + fn try_from(value: u8) -> Result { + Ok(match value { + 1 => PreimageKeyType::Local, + 2 => PreimageKeyType::Keccak256, + 3 => PreimageKeyType::GlobalGeneric, + 4 => PreimageKeyType::Sha256, + 5 => PreimageKeyType::Blob, + _ => anyhow::bail!("Invalid preimage key type"), + }) + } +} + /// A preimage key is a 32-byte value that identifies a preimage that may be fetched from the /// oracle. /// @@ -31,7 +46,7 @@ pub enum PreimageKeyType { /// |---------|-------------| /// | [0, 1) | Type byte | /// | [1, 32) | Data | -#[derive(Debug, Default, Clone, Copy)] +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)] pub struct PreimageKey { data: [u8; 31], key_type: PreimageKeyType, @@ -69,6 +84,15 @@ impl From for [u8; 32] { } } +impl TryFrom<[u8; 32]> for PreimageKey { + type Error = anyhow::Error; + + fn try_from(value: [u8; 32]) -> Result { + let key_type = PreimageKeyType::try_from(value[0])?; + Ok(Self::new(value, key_type)) + } +} + #[cfg(test)] mod test { use super::*; diff --git a/crates/preimage/src/lib.rs b/crates/preimage/src/lib.rs index 7dfaf40b6..61906eb0b 100644 --- a/crates/preimage/src/lib.rs +++ b/crates/preimage/src/lib.rs @@ -10,13 +10,13 @@ mod key; pub use key::{PreimageKey, PreimageKeyType}; mod oracle; -pub use oracle::OracleReader; +pub use oracle::{OracleReader, OracleServer}; mod hint; -pub use hint::HintWriter; +pub use hint::{HintReader, HintWriter}; mod pipe; pub use pipe::PipeHandle; mod traits; -pub use traits::{HintWriterClient, PreimageOracleClient}; +pub use traits::{HintReaderServer, HintWriterClient, PreimageOracleClient, PreimageOracleServer}; diff --git a/crates/preimage/src/oracle.rs b/crates/preimage/src/oracle.rs index 2bd9710e0..cffa23839 100644 --- a/crates/preimage/src/oracle.rs +++ b/crates/preimage/src/oracle.rs @@ -1,4 +1,4 @@ -use crate::{traits::PreimageOracleClient, PipeHandle, PreimageKey}; +use crate::{PipeHandle, PreimageKey, PreimageOracleClient, PreimageOracleServer}; use alloc::vec::Vec; use anyhow::{bail, Result}; @@ -17,7 +17,7 @@ impl OracleReader { /// Set the preimage key for the global oracle reader. This will overwrite any existing key, and /// block until the host has prepared the preimage and responded with the length of the /// preimage. - fn write_key(&mut self, key: PreimageKey) -> Result { + fn write_key(&self, key: PreimageKey) -> Result { // Write the key to the host so that it can prepare the preimage. let key_bytes: [u8; 32] = key.into(); self.pipe_handle.write(&key_bytes)?; @@ -32,7 +32,7 @@ impl OracleReader { impl PreimageOracleClient for OracleReader { /// Get the data corresponding to the currently set key from the host. Return the data in a new /// heap allocated `Vec` - fn get(&mut self, key: PreimageKey) -> Result> { + fn get(&self, key: PreimageKey) -> Result> { let length = self.write_key(key)?; let mut data_buffer = alloc::vec![0; length]; @@ -44,7 +44,7 @@ impl PreimageOracleClient for OracleReader { /// Get the data corresponding to the currently set key from the host. Write the data into the /// provided buffer - fn get_exact(&mut self, key: PreimageKey, buf: &mut [u8]) -> Result<()> { + fn get_exact(&self, key: PreimageKey, buf: &mut [u8]) -> Result<()> { // Write the key to the host and read the length of the preimage. let length = self.write_key(key)?; @@ -59,33 +59,68 @@ impl PreimageOracleClient for OracleReader { } } +/// An [OracleServer] is a router for the host to serve data back to the client [OracleReader]. +#[derive(Debug, Clone, Copy)] +pub struct OracleServer { + pipe_handle: PipeHandle, +} + +impl OracleServer { + /// Create a new [OracleServer] from a [PipeHandle]. + pub fn new(pipe_handle: PipeHandle) -> Self { + Self { pipe_handle } + } +} + +impl PreimageOracleServer for OracleServer { + fn next_preimage_request( + &self, + mut get_preimage: impl FnMut(PreimageKey) -> Result>, + ) -> Result<()> { + // Read the preimage request from the client, and throw early if there isn't is any. + let mut buf = [0u8; 32]; + self.pipe_handle.read_exact(&mut buf)?; + let preimage_key = PreimageKey::try_from(buf)?; + + // Fetch the preimage value from the preimage getter. + let value = get_preimage(preimage_key)?; + + // Write the length as a big-endian u64 followed by the data. + let data = [(value.len() as u64).to_be_bytes().as_ref(), value.as_ref()] + .into_iter() + .flatten() + .copied() + .collect::>(); + self.pipe_handle.write(data.as_slice())?; + + Ok(()) + } +} + #[cfg(test)] mod test { extern crate std; use super::*; use crate::PreimageKeyType; + use alloy_primitives::keccak256; use kona_common::FileDescriptor; - use std::{fs::File, os::fd::AsRawFd}; + use std::{collections::HashMap, fs::File, os::fd::AsRawFd}; use tempfile::tempfile; - /// Test struct containing the [OracleReader] and a [PipeHandle] for the host, plus the open + /// Test struct containing the [OracleReader] and a [OracleServer] for the host, plus the open /// [File]s. The [File]s are stored in this struct so that they are not dropped until the /// end of the test. - /// - /// TODO: Swap host pipe handle to oracle writer once it exists. #[derive(Debug)] struct ClientAndHost { oracle_reader: OracleReader, - host_handle: PipeHandle, + oracle_server: OracleServer, _read_file: File, _write_file: File, } - /// Helper for creating a new [OracleReader] and [PipeHandle] for testing. The file channel is + /// Helper for creating a new [OracleReader] and [OracleServer] for testing. The file channel is /// over two temporary files. - /// - /// TODO: Swap host pipe handle to oracle writer once it exists. fn client_and_host() -> ClientAndHost { let (read_file, write_file) = (tempfile().unwrap(), tempfile().unwrap()); let (read_fd, write_fd) = ( @@ -96,27 +131,48 @@ mod test { let host_handle = PipeHandle::new(write_fd, read_fd); let oracle_reader = OracleReader::new(client_handle); + let oracle_server = OracleServer::new(host_handle); - ClientAndHost { oracle_reader, host_handle, _read_file: read_file, _write_file: write_file } + ClientAndHost { + oracle_reader, + oracle_server, + _read_file: read_file, + _write_file: write_file, + } } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] - async fn test_oracle_reader() { - const MOCK_DATA: &[u8] = b"1234567890"; + async fn test_oracle_client_and_host() { + const MOCK_DATA_A: &[u8] = b"1234567890"; + const MOCK_DATA_B: &[u8] = b"FACADE"; + let key_a: PreimageKey = + PreimageKey::new(*keccak256(MOCK_DATA_A), PreimageKeyType::Keccak256); + let key_b: PreimageKey = + PreimageKey::new(*keccak256(MOCK_DATA_B), PreimageKeyType::Keccak256); + + let mut preimages = HashMap::new(); + preimages.insert(key_a, MOCK_DATA_A.to_vec()); + preimages.insert(key_b, MOCK_DATA_B.to_vec()); + let sys = client_and_host(); - let (mut oracle_reader, host_handle) = (sys.oracle_reader, sys.host_handle); + let (oracle_reader, oracle_server) = (sys.oracle_reader, sys.oracle_server); let client = tokio::task::spawn(async move { - oracle_reader.get(PreimageKey::new([0u8; 32], PreimageKeyType::Keccak256)).unwrap() + let contents_a = oracle_reader.get(key_a).unwrap(); + let contents_b = oracle_reader.get(key_b).unwrap(); + (contents_a, contents_b) }); let host = tokio::task::spawn(async move { - let mut length_and_data: [u8; 8 + 10] = [0u8; 8 + 10]; - length_and_data[0..8].copy_from_slice(&u64::to_be_bytes(MOCK_DATA.len() as u64)); - length_and_data[8..18].copy_from_slice(MOCK_DATA); - host_handle.write(&length_and_data).unwrap(); + let get_preimage = + |key| preimages.get(&key).ok_or(anyhow::anyhow!("Preimage not available")).cloned(); + + oracle_server.next_preimage_request(get_preimage).unwrap(); + oracle_server.next_preimage_request(get_preimage).unwrap(); }); - let (r, _) = tokio::join!(client, host); - assert_eq!(r.unwrap(), MOCK_DATA); + let (client, _) = tokio::join!(client, host); + let (contents_a, contents_b) = client.unwrap(); + assert_eq!(contents_a, MOCK_DATA_A); + assert_eq!(contents_b, MOCK_DATA_B); } } diff --git a/crates/preimage/src/traits.rs b/crates/preimage/src/traits.rs index 4954701c8..cc89a5da7 100644 --- a/crates/preimage/src/traits.rs +++ b/crates/preimage/src/traits.rs @@ -1,5 +1,5 @@ use crate::PreimageKey; -use alloc::vec::Vec; +use alloc::{string::String, vec::Vec}; use anyhow::Result; /// A [PreimageOracleClient] is a high-level interface to read data from the host, keyed by a @@ -11,7 +11,7 @@ pub trait PreimageOracleClient { /// # Returns /// - `Ok(Vec)` if the data was successfully fetched from the host. /// - `Err(_)` if the data could not be fetched from the host. - fn get(&mut self, key: PreimageKey) -> Result>; + fn get(&self, key: PreimageKey) -> Result>; /// Get the data corresponding to the currently set key from the host. Writes the data into the /// provided buffer. @@ -19,7 +19,7 @@ pub trait PreimageOracleClient { /// # Returns /// - `Ok(())` if the data was successfully written into the buffer. /// - `Err(_)` if the data could not be written into the buffer. - fn get_exact(&mut self, key: PreimageKey, buf: &mut [u8]) -> Result<()>; + fn get_exact(&self, key: PreimageKey, buf: &mut [u8]) -> Result<()>; } /// A [HintWriterClient] is a high-level interface to the hint pipe. It provides a way to write @@ -33,3 +33,29 @@ pub trait HintWriterClient { /// - `Err(_)` if the hint could not be written to the host. fn write(&self, hint: &str) -> Result<()>; } + +/// A [PreimageOracleServer] is a high-level interface to accept read requests from the client and +/// write the preimage data to the client pipe. +pub trait PreimageOracleServer { + /// Get the next preimage request and return the response to the client. + /// + /// # Returns + /// - `Ok(())` if the data was successfully written into the client pipe. + /// - `Err(_)` if the data could not be written to the client. + fn next_preimage_request( + &self, + get_preimage: impl FnMut(PreimageKey) -> Result>, + ) -> Result<()>; +} + +/// A [HintReaderServer] is a high-level interface to read preimage hints from the +/// [HintWriterClient] and prepare them for consumption by the client program. +pub trait HintReaderServer { + /// Get the next hint request and return the acknowledgement to the client. + /// + /// # Returns + /// - `Ok(())` if the hint was received and the client was notified of the host's + /// acknowledgement. + /// - `Err(_)` if the hint was not received correctly. + fn next_hint(&self, route_hint: impl FnMut(String) -> Result<()>) -> Result<()>; +}