diff --git a/Cargo.lock b/Cargo.lock index 3abaed11..68f03c51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom", + "getrandom 0.2.8", "once_cell", "version_check", ] @@ -76,7 +76,7 @@ name = "air-interpreter-cid" version = "0.2.0" dependencies = [ "cid", - "multihash", + "multihash 0.18.1", "serde", "serde_json", ] @@ -87,6 +87,7 @@ version = "0.7.0" dependencies = [ "air-interpreter-cid", "air-interpreter-interface", + "air-interpreter-signatures", "air-utils", "aquavm-air-parser", "newtype_derive", @@ -109,6 +110,22 @@ dependencies = [ "serde_json", ] +[[package]] +name = "air-interpreter-signatures" +version = "0.1.0" +dependencies = [ + "air-interpreter-cid", + "base64ct", + "bs58", + "ed25519-dalek", + "fluence-keypair", + "rand_chacha 0.2.2", + "serde", + "serde_json", + "sha2 0.10.6", + "zeroize", +] + [[package]] name = "air-lambda-ast" version = "0.1.0" @@ -290,6 +307,7 @@ dependencies = [ "air-interpreter-cid", "air-interpreter-data", "air-interpreter-interface", + "air-interpreter-signatures", "air-lambda-ast", "air-lambda-parser", "air-log-targets", @@ -304,6 +322,7 @@ dependencies = [ "csv", "env_logger 0.7.1", "fluence-app-service", + "fluence-keypair", "fstrings", "log", "maplit", @@ -363,6 +382,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + [[package]] name = "arrayvec" version = "0.7.2" @@ -378,6 +403,31 @@ dependencies = [ "term", ] +[[package]] +name = "asn1_der" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fce6b6a0ffdafebd82c87e79e3f40e8d2c523e5fea5566ff6b90509bf98d638" +dependencies = [ + "asn1_der_derive", +] + +[[package]] +name = "asn1_der" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" + +[[package]] +name = "asn1_der_derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" +dependencies = [ + "quote", + "syn 1.0.107", +] + [[package]] name = "async-trait" version = "0.1.66" @@ -463,6 +513,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bimap" version = "0.6.3" @@ -499,6 +555,50 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake2b_simd" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "blake2s_simd" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "blake3" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.3" @@ -514,6 +614,12 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + [[package]] name = "bumpalo" version = "3.12.0" @@ -532,6 +638,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + [[package]] name = "bytesize" version = "1.1.0" @@ -577,7 +689,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "103e94d97d73504c5fa6ffb47135d5627ce5ff84a4ad37e8219103ddc291de24" dependencies = [ "ambient-authority", - "rand", + "rand 0.8.5", ] [[package]] @@ -677,7 +789,7 @@ checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" dependencies = [ "core2", "multibase", - "multihash", + "multihash 0.18.1", "serde", "unsigned-varint", ] @@ -791,6 +903,12 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "constant_time_eq" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" + [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -1063,6 +1181,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "csv" version = "1.2.0" @@ -1094,6 +1222,19 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + [[package]] name = "cxx" version = "1.0.91" @@ -1211,13 +1352,22 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +[[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.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer", + "block-buffer 0.10.3", "crypto-common", ] @@ -1272,6 +1422,31 @@ dependencies = [ "winapi", ] +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "serde", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "serde", + "serde_bytes", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "either" version = "1.8.1" @@ -1419,6 +1594,29 @@ dependencies = [ "wast 8.0.0", ] +[[package]] +name = "fluence-keypair" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ed0ab3b8a69317a0452fdb52e35613a8ac5e4a638b21c774ed1ae9195662b" +dependencies = [ + "asn1_der 0.6.3", + "bs58", + "ed25519-dalek", + "eyre", + "lazy_static", + "libp2p-identity", + "libsecp256k1", + "multihash 0.18.1", + "rand 0.8.5", + "ring", + "serde", + "serde_bytes", + "sha2 0.10.6", + "thiserror", + "zeroize", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1486,6 +1684,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -1568,6 +1777,27 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac", +] + [[package]] name = "humantime" version = "1.3.0" @@ -1787,6 +2017,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + [[package]] name = "lalrpop" version = "0.19.12" @@ -1836,6 +2075,76 @@ version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "libp2p-identity" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a8ea433ae0cea7e3315354305237b9897afe45278b2118a7a57ca744e70fd27" +dependencies = [ + "asn1_der 0.7.6", + "bs58", + "ed25519-dalek", + "libsecp256k1", + "log", + "multiaddr", + "multihash 0.17.0", + "prost", + "quick-protobuf", + "rand 0.8.5", + "ring", + "sha2 0.10.6", + "thiserror", + "zeroize", +] + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "link-cplusplus" version = "1.0.8" @@ -2186,6 +2495,25 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "multiaddr" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b36f567c7099511fa8612bbbb52dda2419ce0bdbacf31714e3a5ffdb766d3bd" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "log", + "multibase", + "multihash 0.17.0", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + [[package]] name = "multibase" version = "0.9.1" @@ -2197,16 +2525,33 @@ dependencies = [ "data-encoding-macro", ] +[[package]] +name = "multihash" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" +dependencies = [ + "core2", + "digest 0.10.6", + "multihash-derive", + "sha2 0.10.6", + "unsigned-varint", +] + [[package]] name = "multihash" version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" dependencies = [ + "blake2b_simd", + "blake2s_simd", + "blake3", "core2", - "digest", + "digest 0.10.6", "multihash-derive", - "sha2", + "sha2 0.10.6", + "sha3", "unsigned-varint", ] @@ -2349,6 +2694,12 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "os_str_bytes" version = "6.4.1" @@ -2577,6 +2928,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.107", +] + [[package]] name = "psm" version = "0.1.21" @@ -2592,6 +2966,15 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-protobuf" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +dependencies = [ + "byteorder", +] + [[package]] name = "quote" version = "1.0.26" @@ -2601,6 +2984,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -2608,8 +3004,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -2619,7 +3025,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -2628,7 +3043,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.8", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -2668,7 +3092,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom", + "getrandom 0.2.8", "redox_syscall", "thiserror", ] @@ -2717,6 +3141,21 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -2857,9 +3296,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -2894,6 +3333,19 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.6" @@ -2902,7 +3354,17 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.6", +] + +[[package]] +name = "sha3" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54c2bb1a323307527314a36bfb73f24febb08ce2b8a554bf4ffd6f51ad15198c" +dependencies = [ + "digest 0.10.6", + "keccak", ] [[package]] @@ -2923,6 +3385,12 @@ dependencies = [ "dirs", ] +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + [[package]] name = "siphasher" version = "0.3.10" @@ -2941,12 +3409,24 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.4" @@ -2988,6 +3468,12 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.107" @@ -3305,6 +3791,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.3.1" @@ -3381,6 +3873,12 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -3600,7 +4098,7 @@ dependencies = [ "log", "rustix 0.36.8", "serde", - "sha2", + "sha2 0.10.6", "toml", "windows-sys 0.42.0", "zstd", @@ -3709,7 +4207,7 @@ dependencies = [ "memfd", "memoffset 0.6.5", "paste", - "rand", + "rand 0.8.5", "rustix 0.36.8", "wasmtime-asm-macros", "wasmtime-environ", @@ -4040,6 +4538,26 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +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.10", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/Cargo.toml b/Cargo.toml index 3b52506e..05318d7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ members = [ "crates/air-lib/interpreter-cid", "crates/air-lib/interpreter-data", "crates/air-lib/interpreter-interface", + "crates/air-lib/interpreter-signatures", "crates/air-lib/lambda/ast", "crates/air-lib/lambda/parser", "crates/air-lib/log-targets", diff --git a/air/Cargo.toml b/air/Cargo.toml index 15cf7985..c3404bb9 100644 --- a/air/Cargo.toml +++ b/air/Cargo.toml @@ -20,6 +20,7 @@ aquavm-air-parser = { version = "0.7.4", path = "../crates/air-lib/air-parser" } air-execution-info-collector = { version = "0.7.4", path = "../crates/air-lib/execution-info-collector" } air-interpreter-cid = { version = "0.2.0", path = "../crates/air-lib/interpreter-cid" } air-interpreter-data = { version = "0.7.0", path = "../crates/air-lib/interpreter-data" } +air-interpreter-signatures = { version = "0.1.0", path = "../crates/air-lib/interpreter-signatures" } air-interpreter-interface = { version = "0.13.0", path = "../crates/air-lib/interpreter-interface", default-features = false } air-log-targets = { version = "0.1.0", path = "../crates/air-lib/log-targets" } air-lambda-ast = { version = "0.1.0", path = "../crates/air-lib/lambda/ast" } @@ -27,6 +28,7 @@ air-lambda-parser = { version = "0.1.0", path = "../crates/air-lib/lambda/parser air-trace-handler = { version = "0.2.0", path = "../crates/air-lib/trace-handler" } air-utils = { version = "0.1.0", path = "../crates/air-lib/utils" } polyplets = { version = "0.3.2", path = "../crates/air-lib/polyplets" } +fluence-keypair = { version = "0.10.1" } serde = { version = "1.0.159", features = [ "derive", "rc" ] } serde_json = "1.0.95" diff --git a/air/src/execution_step/execution_context/context.rs b/air/src/execution_step/execution_context/context.rs index e168c1d5..0607ff1a 100644 --- a/air/src/execution_step/execution_context/context.rs +++ b/air/src/execution_step/execution_context/context.rs @@ -21,10 +21,15 @@ use super::Scalars; use super::Streams; use air_execution_info_collector::InstructionTracker; +use air_interpreter_cid::CID; +use air_interpreter_data::CanonResultCidAggregate; use air_interpreter_data::CidInfo; use air_interpreter_data::GlobalStreamGens; use air_interpreter_data::RestrictedStreamGens; +use air_interpreter_data::ServiceResultCidAggregate; use air_interpreter_interface::*; +use air_interpreter_signatures::SignatureStore; +use air_interpreter_signatures::SignatureTracker; use std::rc::Rc; @@ -69,6 +74,17 @@ pub(crate) struct ExecutionCtx<'i> { /// CID-to-something trackers. pub(crate) cid_state: ExecutionCidState, + + /// Signatures' store. + /// + /// It contains peers' signatures for verification. + pub(crate) signature_store: SignatureStore, + + /// Local signatures tracker. + /// + /// It gathers peers' CIDs (call results and canon results) stored in the trace either for signing (current peer's + /// CIDs) or sign verification (other peers). + pub(crate) signature_tracker: SignatureTracker, } impl<'i> ExecutionCtx<'i> { @@ -87,6 +103,9 @@ impl<'i> ExecutionCtx<'i> { ); let cid_state = ExecutionCidState::from_cid_info(prev_ingredients.cid_info, current_ingredients.cid_info); + // TODO we might keep both stores and merge them only with signature info collected into SignatureTracker + let signature_store = + SignatureStore::merge(prev_ingredients.signature_store, current_ingredients.signature_store); Self { run_parameters, @@ -95,6 +114,7 @@ impl<'i> ExecutionCtx<'i> { call_results, streams, cid_state, + signature_store, ..<_>::default() } } @@ -107,6 +127,14 @@ impl<'i> ExecutionCtx<'i> { self.last_call_request_id += 1; self.last_call_request_id } + + pub(crate) fn record_call_cid(&mut self, peer_id: impl Into>, cid: &CID) { + self.signature_tracker.register(peer_id, cid); + } + + pub(crate) fn record_canon_cid(&mut self, peer_id: impl Into>, cid: &CID) { + self.signature_tracker.register(peer_id, cid); + } } impl ExecutionCtx<'_> { @@ -134,6 +162,7 @@ pub(crate) struct ExecCtxIngredients { pub(crate) last_call_request_id: u32, pub(crate) restricted_streams: RestrictedStreamGens, pub(crate) cid_info: CidInfo, + pub(crate) signature_store: SignatureStore, } use serde::Deserialize; diff --git a/air/src/execution_step/instructions/call/call_result_setter.rs b/air/src/execution_step/instructions/call/call_result_setter.rs index 29b7af85..eabf6aea 100644 --- a/air/src/execution_step/instructions/call/call_result_setter.rs +++ b/air/src/execution_step/instructions/call/call_result_setter.rs @@ -38,6 +38,7 @@ pub(crate) fn populate_context_from_peer_service_result<'i>( ) -> ExecutionResult { match output { CallOutputValue::Scalar(scalar) => { + let peer_id: Box = tetraplet.peer_pk.as_str().into(); let service_result_agg_cid = exec_ctx .cid_state .insert_value(executed_result.result.clone(), tetraplet, argument_hash) @@ -45,9 +46,11 @@ pub(crate) fn populate_context_from_peer_service_result<'i>( let executed_result = ValueAggregate::from_service_result(executed_result, service_result_agg_cid.clone()); exec_ctx.scalars.set_scalar_value(scalar.name, executed_result)?; + exec_ctx.record_call_cid(peer_id, &service_result_agg_cid); Ok(CallResult::executed_scalar(service_result_agg_cid)) } CallOutputValue::Stream(stream) => { + let peer_id: Box = tetraplet.peer_pk.as_str().into(); let service_result_agg_cid = exec_ctx .cid_state .insert_value(executed_result.result.clone(), tetraplet, argument_hash) @@ -63,6 +66,7 @@ pub(crate) fn populate_context_from_peer_service_result<'i>( stream.position, ); let generation = exec_ctx.streams.add_stream_value(value_descriptor)?; + exec_ctx.record_call_cid(&*peer_id, &service_result_agg_cid); Ok(CallResult::executed_stream(service_result_agg_cid, generation)) } CallOutputValue::None => { diff --git a/air/src/execution_step/instructions/call/prev_result_handler.rs b/air/src/execution_step/instructions/call/prev_result_handler.rs index 130a9396..dd45587f 100644 --- a/air/src/execution_step/instructions/call/prev_result_handler.rs +++ b/air/src/execution_step/instructions/call/prev_result_handler.rs @@ -61,6 +61,7 @@ pub(super) fn handle_prev_state<'i>( serde_json::from_value((*err_value).clone()).map_err(UncatchableError::MalformedCallServiceFailed)?; exec_ctx.make_subgraph_incomplete(); + exec_ctx.record_call_cid(&*tetraplet.peer_pk, failed_cid); trace_ctx.meet_call_end(met_result.result); let err_msg = call_service_failed.message; @@ -101,6 +102,8 @@ pub(super) fn handle_prev_state<'i>( } // this instruction's been already executed Executed(value) => { + use air_interpreter_data::ValueRef; + let resulted_value = populate_context_from_data( value, tetraplet.clone(), @@ -109,6 +112,14 @@ pub(super) fn handle_prev_state<'i>( output, exec_ctx, )?; + + match &resulted_value { + ValueRef::Scalar(ref cid) | ValueRef::Stream { ref cid, .. } => { + exec_ctx.record_call_cid(&*tetraplet.peer_pk, cid); + } + ValueRef::Unused(_) => {} + } + let call_result = CallResult::Executed(resulted_value); trace_ctx.meet_call_end(call_result); @@ -170,11 +181,13 @@ fn handle_service_error( let failed_value = CallServiceFailed::new(service_result.ret_code, error_message).to_value(); + let peer_id: Box = tetraplet.peer_pk.as_str().into(); let service_result_agg_cid = exec_ctx .cid_state .insert_value(failed_value.into(), tetraplet, argument_hash) .map_err(UncatchableError::from)?; + exec_ctx.record_call_cid(peer_id, &service_result_agg_cid); trace_ctx.meet_call_end(Failed(service_result_agg_cid)); Err(error.into()) diff --git a/air/src/execution_step/instructions/canon.rs b/air/src/execution_step/instructions/canon.rs index 446260eb..d07d3230 100644 --- a/air/src/execution_step/instructions/canon.rs +++ b/air/src/execution_step/instructions/canon.rs @@ -59,6 +59,8 @@ fn handle_seen_canon( let tetraplet_cid = canon_result_agg.tetraplet.clone(); let tetraplet = exec_ctx.cid_state.get_tetraplet_by_cid(&tetraplet_cid)?; + exec_ctx.record_canon_cid(&*tetraplet.peer_pk, &canon_result_cid); + let value_cids = canon_result_agg.values.clone(); let values = value_cids .iter() @@ -149,10 +151,11 @@ fn create_canon_stream_from_name( .record_value(canon_value_aggregate)?) }) .collect::>()?; + let tetraplet = canon_stream.tetraplet(); let tetraplet_cid = exec_ctx .cid_state .tetraplet_tracker - .record_value(canon_stream.tetraplet().clone()) + .record_value(tetraplet.clone()) .map_err(UncatchableError::from)?; let canon_result = CanonResultCidAggregate::new(tetraplet_cid, value_cids); @@ -162,6 +165,8 @@ fn create_canon_stream_from_name( .record_value(canon_result) .map_err(UncatchableError::from)?; + exec_ctx.record_canon_cid(&*tetraplet.peer_pk, &canon_result_cid); + let result = StreamWithSerializedView { canon_stream, canon_result_cid, diff --git a/air/src/farewell_step/outcome.rs b/air/src/farewell_step/outcome.rs index fc2daa14..39077c4d 100644 --- a/air/src/farewell_step/outcome.rs +++ b/air/src/farewell_step/outcome.rs @@ -25,6 +25,7 @@ use crate::INTERPRETER_SUCCESS; use air_interpreter_data::InterpreterData; use air_interpreter_interface::CallRequests; use air_utils::measure; +use fluence_keypair::KeyPair; use std::fmt::Debug; use std::hash::Hash; @@ -36,6 +37,7 @@ use std::rc::Rc; pub(crate) fn from_success_result( exec_ctx: ExecutionCtx<'_>, trace_handler: TraceHandler, + keypair: &KeyPair, ) -> Result { let (ret_code, error_message) = if exec_ctx.call_results.is_empty() { (INTERPRETER_SUCCESS, String::new()) @@ -44,7 +46,7 @@ pub(crate) fn from_success_result( (farewell_error.to_error_code(), farewell_error.to_string()) }; - let outcome = populate_outcome_from_contexts(exec_ctx, trace_handler, ret_code, error_message); + let outcome = populate_outcome_from_contexts(exec_ctx, trace_handler, ret_code, error_message, keypair); Ok(outcome) } @@ -64,21 +66,29 @@ pub(crate) fn from_uncatchable_error( /// Create InterpreterOutcome from supplied execution context, trace handler, and error, /// set ret_code based on the error. -#[tracing::instrument(skip(exec_ctx, trace_handler))] +#[tracing::instrument(skip(exec_ctx, trace_handler, keypair))] pub(crate) fn from_execution_error( exec_ctx: ExecutionCtx<'_>, trace_handler: TraceHandler, error: impl ToErrorCode + ToString + Debug, + keypair: &KeyPair, ) -> InterpreterOutcome { - populate_outcome_from_contexts(exec_ctx, trace_handler, error.to_error_code(), error.to_string()) + populate_outcome_from_contexts( + exec_ctx, + trace_handler, + error.to_error_code(), + error.to_string(), + keypair, + ) } -#[tracing::instrument(skip(exec_ctx, trace_handler), level = "info")] +#[tracing::instrument(skip(exec_ctx, trace_handler, keypair), level = "info")] fn populate_outcome_from_contexts( - exec_ctx: ExecutionCtx<'_>, + mut exec_ctx: ExecutionCtx<'_>, mut trace_handler: TraceHandler, ret_code: i64, error_message: String, + keypair: &KeyPair, ) -> InterpreterOutcome { let maybe_gens = exec_ctx .streams @@ -89,11 +99,19 @@ fn populate_outcome_from_contexts( Err(outcome) => return outcome, }; + let current_signature = exec_ctx + .signature_tracker + .into_signature(&exec_ctx.run_parameters.current_peer_id, keypair) + .expect("siging shouldn't fail"); + let current_pubkey = keypair.public(); + exec_ctx.signature_store.put(current_pubkey.into(), current_signature); + let data = InterpreterData::from_execution_result( trace_handler.into_result_trace(), global_streams, restricted_streams, exec_ctx.cid_state.into(), + exec_ctx.signature_store, exec_ctx.last_call_request_id, semver::Version::parse(env!("CARGO_PKG_VERSION")).expect("cargo version is valid"), ); diff --git a/air/src/preparation_step/preparation.rs b/air/src/preparation_step/preparation.rs index 1bc3e905..5f674c88 100644 --- a/air/src/preparation_step/preparation.rs +++ b/air/src/preparation_step/preparation.rs @@ -53,6 +53,7 @@ pub(crate) fn prepare<'i>( last_call_request_id: prev_data.last_call_request_id, restricted_streams: prev_data.restricted_streams, cid_info: prev_data.cid_info, + signature_store: prev_data.signatures, }; let current_ingredients = ExecCtxIngredients { @@ -60,6 +61,7 @@ pub(crate) fn prepare<'i>( last_call_request_id: current_data.last_call_request_id, restricted_streams: current_data.restricted_streams, cid_info: current_data.cid_info, + signature_store: current_data.signatures, }; let exec_ctx = make_exec_ctx(prev_ingredients, current_ingredients, call_results, run_parameters)?; diff --git a/air/src/runner.rs b/air/src/runner.rs index 54c2bc07..c8bd15c2 100644 --- a/air/src/runner.rs +++ b/air/src/runner.rs @@ -21,6 +21,7 @@ use crate::preparation_step::PreparationDescriptor; use air_interpreter_interface::InterpreterOutcome; use air_interpreter_interface::RunParameters; +use air_interpreter_signatures::derive_dummy_keypair; use air_log_targets::RUN_PARAMS; use air_utils::measure; @@ -55,6 +56,9 @@ fn execute_air_impl( params: RunParameters, call_results: Vec, ) -> Result { + // TODO STUB this is a stub key that is to be replaced by external one in other PR + let (keypair, _) = derive_dummy_keypair(¶ms.current_peer_id); + let PreparationDescriptor { mut exec_ctx, mut trace_handler, @@ -72,11 +76,17 @@ fn execute_air_impl( tracing::Level::INFO, "execute", ); - match exec_result { - Ok(_) => farewell::from_success_result(exec_ctx, trace_handler), - // return new collected trace in case of errors - Err(error) if error.is_catchable() => Err(farewell::from_execution_error(exec_ctx, trace_handler, error)), - // return the prev data in case of any trace errors - Err(error) => Err(farewell::from_uncatchable_error(prev_data, error)), - } + measure!( + match exec_result { + Ok(_) => farewell::from_success_result(exec_ctx, trace_handler, &keypair), + // return new collected trace in case of errors + Err(error) if error.is_catchable() => { + Err(farewell::from_execution_error(exec_ctx, trace_handler, error, &keypair)) + } + // return the prev data in case of any trace errors + Err(error) => Err(farewell::from_uncatchable_error(prev_data, error)), + }, + tracing::Level::INFO, + "farewell", + ) } diff --git a/air/tests/test_module/features/mod.rs b/air/tests/test_module/features/mod.rs index dd0daba9..4b3c0013 100644 --- a/air/tests/test_module/features/mod.rs +++ b/air/tests/test_module/features/mod.rs @@ -21,5 +21,6 @@ mod join_behaviour; mod lambda; mod misc; mod scopes; +mod signatures; mod streams; mod tetraplets; diff --git a/air/tests/test_module/features/signatures.rs b/air/tests/test_module/features/signatures.rs new file mode 100644 index 00000000..df6754a4 --- /dev/null +++ b/air/tests/test_module/features/signatures.rs @@ -0,0 +1,444 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use air_interpreter_signatures::{derive_dummy_keypair, SignatureTracker}; +use air_test_framework::{ephemeral::PeerId, AirScriptExecutor}; +use air_test_utils::prelude::*; +use air_test_utils::test_runner::TestRunParameters; + +#[test] +fn test_signature_empty() { + let script = "(null)"; + let init_peer_id = "init_peer_id"; + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let exec = AirScriptExecutor::new( + TestRunParameters::from_init_peer_id(init_peer_id), + vec![], + vec![PeerId::from(init_peer_id)].into_iter(), + script, + ) + .unwrap(); + let res = exec.execute_one(init_peer_id).unwrap(); + assert_eq!(res.ret_code, 0, "{:?}", res); + + let expected_signature: air_interpreter_signatures::Signature = keypair.sign(b"[]").unwrap().into(); + + let data = data_from_result(&res); + let signature = data.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", data.signatures); +} + +#[test] +fn test_signature_call_var() { + let init_peer_id = "init_peer_id"; + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let air_script = format!( + r#" + (call "{init_peer_id}" ("" "") [] var) ; ok = "ok" + "# + ); + let exec = AirScriptExecutor::simple(TestRunParameters::from_init_peer_id(init_peer_id), &air_script).unwrap(); + + let res = exec.execution_iter(init_peer_id).unwrap().last().unwrap(); + assert_eq!(res.ret_code, 0, "{:?}", res); + let data = data_from_result(&res); + + let expected_call_state = scalar!("ok", peer = init_peer_id, service = "..0"); + let expected_cid = extract_service_result_cid(&expected_call_state); + + let mut expected_tracker = SignatureTracker::new(); + expected_tracker.register(init_peer_id, &expected_cid); + let expected_signature = expected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + let signature = data.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", data.signatures); +} + +#[test] +fn test_signature_call_stream() { + let init_peer_id = "init_peer_id"; + let air_script = format!( + r#" + (call "{init_peer_id}" ("" "") [] $var) ; ok = "ok" + "# + ); + let exec = AirScriptExecutor::simple(TestRunParameters::from_init_peer_id(init_peer_id), &air_script).unwrap(); + + let res = exec.execution_iter(init_peer_id).unwrap().last().unwrap(); + assert_eq!(res.ret_code, 0, "{:?}", res); + let data = data_from_result(&res); + + let expected_call_state = stream!("ok", 0, peer = init_peer_id, service = "..0"); + let expected_cid = extract_service_result_cid(&expected_call_state); + + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let mut expected_tracker = SignatureTracker::new(); + expected_tracker.register(init_peer_id, &expected_cid); + let expected_signature = expected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + let signature = data.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", data.signatures); +} + +#[test] +fn test_signature_call_ununsed() { + let init_peer_id = "init_peer_id"; + let air_script = format!( + r#" + (call "{init_peer_id}" ("" "") []) ; ok = "ok" + "# + ); + let exec = AirScriptExecutor::simple(TestRunParameters::from_init_peer_id(init_peer_id), &air_script).unwrap(); + + let res = exec.execution_iter(init_peer_id).unwrap().last().unwrap(); + assert_eq!(res.ret_code, 0, "{:?}", res); + let data = data_from_result(&res); + + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let mut expected_tracker = SignatureTracker::new(); + let expected_signature = expected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + let signature = data.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", data.signatures); +} + +#[test] +fn test_signature_call_merged() { + let init_peer_id = "init_peer_id"; + let other_peer_id = "other_peer_id"; + + let air_script = format!( + r#" + (seq + (call "{init_peer_id}" ("" "") [] x) ; ok = "res0" + (seq + (call "{other_peer_id}" ("" "") [] y) ; ok = "res1" + (call "{init_peer_id}" ("" "") [] z) ; ok = "res2" + )) + "# + ); + + let exec = AirScriptExecutor::simple(TestRunParameters::from_init_peer_id(init_peer_id), &air_script).unwrap(); + let _ = exec.execute_one(init_peer_id).unwrap(); + let _ = exec.execute_one(other_peer_id).unwrap(); + let res2 = exec.execute_one(init_peer_id).unwrap(); + let data2 = data_from_result(&res2); + + let expected_call_state0 = scalar!("res0", peer = init_peer_id, service = "..0"); + let expected_cid0 = extract_service_result_cid(&expected_call_state0); + let expected_call_state2 = scalar!("res2", peer = init_peer_id, service = "..2"); + let expected_cid2 = extract_service_result_cid(&expected_call_state2); + + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let mut expected_tracker = SignatureTracker::new(); + expected_tracker.register(init_peer_id, &expected_cid0); + expected_tracker.register(init_peer_id, &expected_cid2); + let expected_signature = expected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + let signature = data2.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", data2.signatures); +} + +#[test] +fn test_signature_call_double() { + // Test that if some CID appears twice in the call result, it is accounted twice. + let init_peer_id = "init_peer_id"; + let air_script = format!( + r#" + (seq + (seq (ap 1 $s) (ap 2 $s)) + (fold $s i + (seq + (call "{init_peer_id}" ("" "") [] var) ; ok = "ok" + (next i)))) + "# + ); + let exec = AirScriptExecutor::simple(TestRunParameters::from_init_peer_id(init_peer_id), &air_script).unwrap(); + + let res = exec.execution_iter(init_peer_id).unwrap().last().unwrap(); + assert_eq!(res.ret_code, 0, "{:?}", res); + let data = data_from_result(&res); + + let expected_call_state = scalar!("ok", peer = init_peer_id, service = "..0"); + let expected_cid = extract_service_result_cid(&expected_call_state); + + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let mut unexpected_tracker = SignatureTracker::new(); + unexpected_tracker.register(init_peer_id, &expected_cid); + let unexpected_signature = unexpected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + let mut expected_tracker = SignatureTracker::new(); + expected_tracker.register(init_peer_id, &expected_cid); + expected_tracker.register(init_peer_id, &expected_cid); + let expected_signature = expected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + assert_ne!(expected_signature, unexpected_signature, "test is incorrect"); + + let signature = data.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", data.signatures); +} + +#[test] +fn test_signature_canon_basic() { + let init_peer_id = "init_peer_id"; + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let air_script = format!( + r#" + (seq + (call "{init_peer_id}" ("serv" "func") [] items) ; ok = [1, 2, 3] + (seq + (fold items i + (seq + (ap i $stream) + (next i))) + (canon "{init_peer_id}" $stream #canon))) + "# + ); + let exec = AirScriptExecutor::simple(TestRunParameters::from_init_peer_id(init_peer_id), &air_script).unwrap(); + + let last_result = exec.execution_iter(init_peer_id).unwrap().last().unwrap(); + let last_data = data_from_result(&last_result); + + let expected_call_result = scalar!( + json!([1, 2, 3]), + peer = init_peer_id, + service = "serv..0", + function = "func" + ); + let expected_call_result_cid = extract_service_result_cid(&expected_call_result); + + let expected_canon_state = canon(json!({ + "tetraplet": {"peer_pk": init_peer_id, "service_id": "", "function_name": "", "json_path": ""}, + "values": [{ + "result": 1, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[0]", + }, + "provenance": Provenance::service_result(expected_call_result_cid.clone()), + }, { + "result": 2, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[1]", + }, + "provenance": Provenance::service_result(expected_call_result_cid.clone()), + }, { + "result": 3, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[2]", + }, + "provenance": Provenance::service_result(expected_call_result_cid.clone()), + }] + })); + let expected_canon_cid = extract_canon_result_cid(&expected_canon_state); + + let mut expected_tracker = SignatureTracker::new(); + expected_tracker.register(init_peer_id, &expected_canon_cid); + expected_tracker.register(init_peer_id.to_owned(), &expected_call_result_cid); + let expected_signature = expected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + let signature = last_data.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", last_data); +} + +#[test] +fn test_signature_canon_merge() { + let init_peer_id = "init_peer_id"; + let other_peer_id = "other_peer_id"; + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let air_script = format!( + r#" + (seq + (seq + (call "{init_peer_id}" ("serv" "func") [] items) ; ok = [1, 2, 3] + (seq + (fold items i + (seq + (ap i $stream) + (next i))) + (canon "{init_peer_id}" $stream #canon))) + (seq + (call "{other_peer_id}" ("" "") []) ; ok = "ok" + (call "{init_peer_id}" ("" "") []))) ; ok = "ok" + "# + ); + let exec = AirScriptExecutor::simple(TestRunParameters::from_init_peer_id(init_peer_id), &air_script).unwrap(); + + exec.execute_all(init_peer_id); + exec.execute_one(other_peer_id); + + let last_result = exec.execution_iter(init_peer_id).unwrap().last().unwrap(); + let last_data = data_from_result(&last_result); + + let expected_call_result = scalar!( + json!([1, 2, 3]), + peer = init_peer_id, + service = "serv..0", + function = "func" + ); + let expected_call_result_cid = extract_service_result_cid(&expected_call_result); + + let expected_canon_state = canon(json!({ + "tetraplet": {"peer_pk": init_peer_id, "service_id": "", "function_name": "", "json_path": ""}, + "values": [{ + "result": 1, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[0]", + }, + "provenance": Provenance::service_result(expected_call_result_cid.clone()), + }, { + "result": 2, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[1]", + }, + "provenance": Provenance::service_result(expected_call_result_cid.clone()), + }, { + "result": 3, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[2]", + }, + "provenance": Provenance::service_result(expected_call_result_cid.clone()), + }] + })); + let expected_canon_cid = extract_canon_result_cid(&expected_canon_state); + + let mut expected_tracker = SignatureTracker::new(); + expected_tracker.register(init_peer_id, &expected_canon_cid); + expected_tracker.register(init_peer_id, &expected_call_result_cid); + let expected_signature = expected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + let signature = last_data.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", last_data); +} + +#[test] +fn test_signature_canon_result() { + // this test checks that call result in canon doesn't lead to repeadted accounting of the call result + let init_peer_id = "init_peer_id"; + let (keypair, _) = derive_dummy_keypair(init_peer_id); + + let air_script = format!( + r#" + (seq + (seq + (call "{init_peer_id}" ("serv" "func") [] items) ; ok = [1, 2, 3] + (fold items i + (seq + (ap i $stream) + (next i)))) + (seq + (call "{init_peer_id}" ("serv" "func2") [] $stream) ; ok = 42 + (canon "{init_peer_id}" $stream #canon))) + "# + ); + let exec = AirScriptExecutor::simple(TestRunParameters::from_init_peer_id(init_peer_id), &air_script).unwrap(); + + let last_result = exec.execution_iter(init_peer_id).unwrap().last().unwrap(); + let last_data = data_from_result(&last_result); + + let expected_call_result1 = scalar!( + json!([1, 2, 3]), + peer = init_peer_id, + service = "serv..0", + function = "func" + ); + let expected_call_result_cid1 = extract_service_result_cid(&expected_call_result1); + + let expected_call_result2 = stream!( + json!(42), + 1, + peer = init_peer_id, + service = "serv..1", + function = "func2" + ); + let expected_call_result_cid2 = extract_service_result_cid(&expected_call_result2); + + let expected_canon_state = canon(json!({ + "tetraplet": {"peer_pk": init_peer_id, "service_id": "", "function_name": "", "json_path": ""}, + "values": [{ + "result": 1, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[0]", + }, + "provenance": Provenance::service_result(expected_call_result_cid1.clone()), + }, { + "result": 2, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[1]", + }, + "provenance": Provenance::service_result(expected_call_result_cid1.clone()), + }, { + "result": 3, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..0", + "function_name": "func", + "json_path": ".$.[2]", + }, + "provenance": Provenance::service_result(expected_call_result_cid1.clone()), + }, { + "result": 42, + "tetraplet": { + "peer_pk": init_peer_id, + "service_id": "serv..1", + "function_name": "func2", + "json_path": "", + }, + "provenance": Provenance::service_result(expected_call_result_cid2.clone()), + }] + })); + let expected_canon_cid = extract_canon_result_cid(&expected_canon_state); + + let mut expected_tracker = SignatureTracker::new(); + expected_tracker.register(init_peer_id, &expected_call_result_cid1); + expected_tracker.register(init_peer_id, &expected_call_result_cid2); + expected_tracker.register(init_peer_id, &expected_canon_cid); + let expected_signature = expected_tracker.into_signature(init_peer_id, &keypair).unwrap(); + + let signature = last_data.signatures.get(&keypair.public().into()); + assert_eq!(signature, Some(&expected_signature), "{:?}", last_data); +} diff --git a/air/tests/test_module/negative_tests/uncatchable_trace_related.rs b/air/tests/test_module/negative_tests/uncatchable_trace_related.rs index 5dd91cbf..a6ba74a6 100644 --- a/air/tests/test_module/negative_tests/uncatchable_trace_related.rs +++ b/air/tests/test_module/negative_tests/uncatchable_trace_related.rs @@ -310,28 +310,20 @@ fn invalid_dst_generations() { (ap "a" $s) "# ); - // TODO generate data instead, as the code will be apdated on each data change - let data = json!( - { - "version": "0.6.3", - "interpreter_version": "1.1.1", - "trace": [ - {"ap": - {"gens": [42,42]} - } - ], - "streams": {}, - "r_streams": {}, - "lcid": 0, - "cid_info": { - "value_store": {}, - "tetraplet_store": {}, - "canon_element_store": {}, - "canon_result_store": {}, - "service_result_store": {} - } - }); - let data: Vec = serde_json::to_vec(&data).unwrap(); + + let empty_data = InterpreterData::from_execution_result( + <_>::default(), + <_>::default(), + <_>::default(), + <_>::default(), + <_>::default(), + <_>::default(), + semver::Version::new(1, 1, 1), + ); + let mut data_value = serde_json::to_value(&empty_data).unwrap(); + data_value["trace"] = json!([{"ap": {"gens": [42, 42]}}]); + + let data: Vec = serde_json::to_vec(&data_value).unwrap(); // let result = peer_vm_1.call(script, "", data, <_>::default()).unwrap(); let result = call_vm!(peer_vm_1, <_>::default(), &script, "", data); let expected_error = UncatchableError::TraceError { diff --git a/crates/air-lib/interpreter-cid/src/lib.rs b/crates/air-lib/interpreter-cid/src/lib.rs index 104cd2ae..de55c260 100644 --- a/crates/air-lib/interpreter-cid/src/lib.rs +++ b/crates/air-lib/interpreter-cid/src/lib.rs @@ -32,7 +32,7 @@ use serde::Serialize; use std::fmt; use std::marker::PhantomData; -#[derive(Clone, Serialize, Deserialize)] +#[derive(Serialize, Deserialize)] #[serde(transparent)] pub struct CID(String, #[serde(skip)] PhantomData<*const T>); @@ -46,6 +46,11 @@ impl CID { } } +impl Clone for CID { + fn clone(&self) -> Self { + Self(self.0.clone(), self.1) + } +} impl fmt::Debug for CID { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("CID").field(&self.0).finish() diff --git a/crates/air-lib/interpreter-data/Cargo.toml b/crates/air-lib/interpreter-data/Cargo.toml index 07f4c28b..71a185c2 100644 --- a/crates/air-lib/interpreter-data/Cargo.toml +++ b/crates/air-lib/interpreter-data/Cargo.toml @@ -19,6 +19,7 @@ air-utils = { version = "0.1.0", path = "../utils" } aquavm-air-parser = { version = "0.7.4", path = "../air-parser" } air-interpreter-interface = { version = "0.13.0", path = "../interpreter-interface" } air-interpreter-cid = { version = "0.2.0", path = "../interpreter-cid" } +air-interpreter-signatures = { version = "0.1.0", path = "../interpreter-signatures" } polyplets = { version = "0.3.2", path = "../polyplets" } serde = {version = "1.0.159", features = ["derive", "rc"]} diff --git a/crates/air-lib/interpreter-data/src/executed_state/impls.rs b/crates/air-lib/interpreter-data/src/executed_state/impls.rs index 5c861b17..177c67ae 100644 --- a/crates/air-lib/interpreter-data/src/executed_state/impls.rs +++ b/crates/air-lib/interpreter-data/src/executed_state/impls.rs @@ -62,6 +62,18 @@ impl CallResult { pub fn failed(service_result_agg_cid: Rc>) -> CallResult { CallResult::Failed(service_result_agg_cid) } + + pub fn get_cid(&self) -> Option>> { + match self { + CallResult::RequestSentBy(_) => None, + CallResult::Executed(executed) => match executed { + ValueRef::Scalar(cid) => Some(cid.clone()), + ValueRef::Stream { cid, .. } => Some(cid.clone()), + ValueRef::Unused(_) => None, + }, + CallResult::Failed(cid) => Some(cid.clone()), + } + } } impl SubTraceDesc { diff --git a/crates/air-lib/interpreter-data/src/interpreter_data.rs b/crates/air-lib/interpreter-data/src/interpreter_data.rs index 12b2aa35..8c4068f6 100644 --- a/crates/air-lib/interpreter-data/src/interpreter_data.rs +++ b/crates/air-lib/interpreter-data/src/interpreter_data.rs @@ -23,6 +23,7 @@ use crate::ExecutionTrace; use crate::JValue; use crate::ServiceResultCidAggregate; +use air_interpreter_signatures::SignatureStore; use air_utils::measure; use polyplets::SecurityTetraplet; @@ -61,6 +62,12 @@ pub struct InterpreterData { /// CID-to-somethings mappings. pub cid_info: CidInfo, + + /// Signature store. + /// + /// Every peer signs call results and canon values it produced (all together), and stores the signatures + /// in this store. + pub signatures: SignatureStore, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -84,6 +91,7 @@ impl InterpreterData { last_call_request_id: 0, restricted_streams: RestrictedStreamGens::new(), cid_info: <_>::default(), + signatures: <_>::default(), } } @@ -93,6 +101,7 @@ impl InterpreterData { streams: GlobalStreamGens, restricted_streams: RestrictedStreamGens, cid_info: CidInfo, + signatures: SignatureStore, last_call_request_id: u32, interpreter_version: semver::Version, ) -> Self { @@ -105,6 +114,7 @@ impl InterpreterData { last_call_request_id, restricted_streams, cid_info, + signatures, } } @@ -149,50 +159,3 @@ pub struct CidInfo { /// Map CID to a service result aggregate. pub service_result_store: CidStore, } - -#[cfg(test)] -mod tests { - use super::*; - use serde::Deserialize; - use serde::Serialize; - - #[test] - fn compatible_with_0_6_0_version() { - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct InterpreterData0_6_0 { - pub trace: ExecutionTrace, - #[serde(rename = "streams")] // for compatibility with versions <= 0.2.1 - pub global_streams: GlobalStreamGens, - pub version: semver::Version, - #[serde(default)] - #[serde(rename = "lcid")] - pub last_call_request_id: u32, - #[serde(default)] - #[serde(rename = "r_streams")] - pub restricted_streams: RestrictedStreamGens, - pub interpreter_version: semver::Version, - pub cid_info: CidInfo, - } - - // test 0.6.0 to 0.6.1 conversion - let data_0_6_0 = InterpreterData0_6_0 { - trace: ExecutionTrace::default(), - global_streams: GlobalStreamGens::default(), - version: semver::Version::new(0, 2, 0), - last_call_request_id: 0, - restricted_streams: RestrictedStreamGens::default(), - interpreter_version: semver::Version::new(0, 1, 1), - cid_info: CidInfo::default(), - }; - - let data_0_6_0_se = serde_json::to_vec(&data_0_6_0).unwrap(); - let data_0_6_1 = serde_json::from_slice::(&data_0_6_0_se); - assert!(data_0_6_1.is_ok()); - - // test 0.6.1 to 0.6.0 conversion - let data_0_6_1 = InterpreterData::new(semver::Version::new(1, 1, 1)); - let data_0_6_1_se = serde_json::to_vec(&data_0_6_1).unwrap(); - let data_0_6_0 = serde_json::from_slice::(&data_0_6_1_se); - assert!(data_0_6_0.is_ok()); - } -} diff --git a/crates/air-lib/interpreter-signatures/Cargo.toml b/crates/air-lib/interpreter-signatures/Cargo.toml new file mode 100644 index 00000000..a9afffe8 --- /dev/null +++ b/crates/air-lib/interpreter-signatures/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "air-interpreter-signatures" +description = "AIR interpreter signatures util module" +version = "0.1.0" +authors = ["Fluence Labs"] +edition = "2018" +license = "Apache-2.0" +documentation = "https://docs.rs/air-interpreter-signatures" +repository = "https://github.com/fluencelabs/aquavm/tree/master/crates/air-lib/interpreter-signatures" +keywords = ["fluence", "air", "programming-language"] +categories = ["wasm"] + +[dependencies] +air-interpreter-cid = { version = "0.2.0", path = "../interpreter-cid" } +fluence-keypair = "0.10.1" + +base64ct = { version = "1.6.0", features = ["std"] } +serde = { version = "1.0.159", features = ["derive"] } +serde_json = "1.0.96" +zeroize = { version = "1.6.0" } + +# TODO to be moved to test-utils: +ed25519-dalek = "1.0.1" +rand_chacha = "0.2.2" +sha2 = "0.10.6" +bs58 = "0.4.0" diff --git a/crates/air-lib/interpreter-signatures/src/lib.rs b/crates/air-lib/interpreter-signatures/src/lib.rs new file mode 100644 index 00000000..d607b7f7 --- /dev/null +++ b/crates/air-lib/interpreter-signatures/src/lib.rs @@ -0,0 +1,165 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#![forbid(unsafe_code)] +#![warn(rust_2018_idioms)] +#![deny( + dead_code, + nonstandard_style, + unused_imports, + unused_mut, + unused_variables, + unused_unsafe, + unreachable_patterns +)] + +use air_interpreter_cid::CID; +use fluence_keypair::error::SigningError; +use fluence_keypair::KeyPair; +use rand_chacha::rand_core::SeedableRng; +use serde::{Deserialize, Serialize}; + +use std::borrow::Borrow; +use std::collections::HashMap; +use std::hash::Hash; + +/// An opaque serializable representation of public key. +/// +/// It can be string or binary, you shouldn't care about it unless you change serialization format. +// surrent implementation uses string as it is used as a key in a JSON map +#[derive(Debug, Hash, Clone, Eq, PartialEq, PartialOrd, Deserialize, Serialize)] +#[serde(transparent)] +pub struct PublicKey(Box); + +impl From for PublicKey { + fn from(value: fluence_keypair::PublicKey) -> Self { + Self(bs58::encode(&value.to_vec()).into_string().into()) + } +} + +/// An opaque serializable representation of signature key. +/// +/// It can be string or binary, you shouldn't care about it unless you change serialization format. +// surrent implementation uses string as more compact in JSON representation than number array +#[derive(Debug, Hash, Clone, Eq, PartialEq, PartialOrd, Deserialize, Serialize)] +#[serde(transparent)] +pub struct Signature(Box); + +impl Signature { + fn new(signature: fluence_keypair::Signature) -> Self { + signature.into() + } +} + +impl From for Signature { + fn from(value: fluence_keypair::Signature) -> Self { + Self(bs58::encode(value.to_vec()).into_string().into()) + } +} + +#[derive(Debug, Default)] +pub struct SignatureTracker { + peer_to_cids: HashMap, Vec>>, +} + +impl SignatureTracker { + pub fn new() -> Self { + Default::default() + } + + pub fn register(&mut self, peer_id: impl Into>, cid: &CID) { + self.peer_to_cids + .entry(peer_id.into()) + .or_default() + .push(cid.clone().into_inner().into()); + } + + pub fn into_signature( + &mut self, + peer_id: &str, + signer: &KeyPair, + ) -> Result { + let mut cids = self.peer_to_cids.get(peer_id).cloned().unwrap_or_default(); + cids.sort_unstable(); + + // TODO make pluggable serialization + // TODO it will be useful for CID too + // TODO please note that using serde::Serializer is not enough + let serialized_cids = + serde_json::to_string(&cids).expect("default serialization shouldn't fail"); + + signer.sign(serialized_cids.as_bytes()).map(Signature::new) + } +} + +/// A dictionary-like structure that stores peer public keys and their particle data signatures. +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct SignatureStore(HashMap); + +impl SignatureStore { + pub fn new() -> Self { + Default::default() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + pub fn get(&self, peer_pk: &Q) -> Option<&Sign> + where + Key: Borrow, + Q: Hash + Eq + ?Sized, + { + self.0.get(peer_pk) + } + + pub fn put(&mut self, peer_pk: Key, signature: Sign) { + self.0.insert(peer_pk, signature); + } + + pub fn merge(prev: Self, _current: Self) -> Self { + // TODO STUB + prev + } +} + +impl Default for SignatureStore { + fn default() -> Self { + Self(Default::default()) + } +} + +/// Derive fake keypair for testing proposes. +/// +/// This function should be used in production, but it is yet. +/// It returns a keypair determinisitically derived from seed, and a corresponding peer ID +/// that might be useful in tests. +// Should be moved to test lib when keypair interface PR is merged. +pub fn derive_dummy_keypair(seed: &str) -> (KeyPair, String) { + use sha2::{Digest as _, Sha256}; + + let mut rng = { + let mut hasher = Sha256::new(); + hasher.update(seed); + rand_chacha::ChaCha8Rng::from_seed(hasher.finalize().into()) + }; + + let keypair_ed25519 = ed25519_dalek::Keypair::generate(&mut rng); + let keypair: KeyPair = KeyPair::Ed25519(keypair_ed25519.into()); + + let peer_id = keypair.public().to_peer_id().to_string(); + (keypair, peer_id) +} diff --git a/crates/air-lib/test-utils/src/lib.rs b/crates/air-lib/test-utils/src/lib.rs index 0cc311b9..21f8e08c 100644 --- a/crates/air-lib/test-utils/src/lib.rs +++ b/crates/air-lib/test-utils/src/lib.rs @@ -100,6 +100,7 @@ pub fn raw_data_from_trace( <_>::default(), <_>::default(), cid_state.into(), + <_>::default(), 0, semver::Version::new(1, 1, 1), ); @@ -121,6 +122,7 @@ pub fn raw_data_from_trace_with_canon( canon_result_store: cid_state.canon_result_tracker.into(), service_result_store: cid_state.service_result_agg_tracker.into(), }, + <_>::default(), 0, semver::Version::new(1, 1, 1), );