diff --git a/.github/workflows/multichain-integration.yml b/.github/workflows/multichain-integration.yml index cde3a2214..d64af4731 100644 --- a/.github/workflows/multichain-integration.yml +++ b/.github/workflows/multichain-integration.yml @@ -68,6 +68,11 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Install toxiproxy-server + run: | + wget -O toxiproxy-2.9.0_linux_amd64.deb https://github.com/Shopify/toxiproxy/releases/download/v2.9.0/toxiproxy_2.9.0_linux_amd64.deb + sudo dpkg -i toxiproxy-2.9.0_linux_amd64.deb + - name: Configure AWS run: | # Fake AWS configuration for LocalStack diff --git a/infra/scripts/generate_cipher_keys/Cargo.lock b/infra/scripts/generate_cipher_and_sign_keys/Cargo.lock similarity index 63% rename from infra/scripts/generate_cipher_keys/Cargo.lock rename to infra/scripts/generate_cipher_and_sign_keys/Cargo.lock index 66f1d700a..815854f06 100644 --- a/infra/scripts/generate_cipher_keys/Cargo.lock +++ b/infra/scripts/generate_cipher_and_sign_keys/Cargo.lock @@ -38,15 +38,10 @@ dependencies = [ ] [[package]] -name = "ahash" -version = "0.7.8" +name = "anyhow" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "base16ct" @@ -54,6 +49,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -65,48 +69,33 @@ dependencies = [ [[package]] name = "borsh" -version = "0.9.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", - "hashbrown", + "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.9.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", + "once_cell", "proc-macro-crate", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" -dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", + "syn_derive", ] [[package]] -name = "borsh-schema-derive-internal" -version = "0.9.3" +name = "bs58" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "byteorder" @@ -114,12 +103,24 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chacha20" version = "0.9.1" @@ -161,6 +162,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -170,6 +177,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -211,10 +224,13 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", + "digest", "fiat-crypto", "platforms", + "rand_core", "rustc_version", "subtle", + "zeroize", ] [[package]] @@ -225,7 +241,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn", ] [[package]] @@ -238,6 +254,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + [[package]] name = "digest" version = "0.10.7" @@ -249,6 +278,28 @@ dependencies = [ "subtle", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core", + "sha2", + "subtle", +] + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -268,6 +319,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "ff" version = "0.13.0" @@ -284,12 +341,22 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "static_assertions", +] + [[package]] name = "generate_cipher_keys" version = "0.1.0" dependencies = [ "hex", "mpc-keys", + "near-crypto", ] [[package]] @@ -338,18 +405,18 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hkdf" @@ -392,6 +459,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "inout" version = "0.1.3" @@ -401,12 +478,30 @@ dependencies = [ "generic-array", ] +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "json_comments" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbbfed4e59ba9750e15ba154fdfd9329cee16ff3df539c2666b70f58cc32105" + [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + [[package]] name = "mpc-keys" version = "0.1.0" @@ -417,6 +512,59 @@ dependencies = [ "serde", ] +[[package]] +name = "near-account-id" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35cbb989542587b47205e608324ddd391f0cee1c22b4b64ae49f458334b95907" +dependencies = [ + "borsh", + "serde", +] + +[[package]] +name = "near-config-utils" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b3db4ac2d4340caef06b6363c3fd16c0be1f70267908dfa53e2e6241649b0c" +dependencies = [ + "anyhow", + "json_comments", + "thiserror", + "tracing", +] + +[[package]] +name = "near-crypto" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9807fb257f7dda41383bb33e14cfd4a8840ffa7932cb972db9eabff19ce3bf4" +dependencies = [ + "blake2", + "borsh", + "bs58", + "curve25519-dalek", + "derive_more", + "ed25519-dalek", + "hex", + "near-account-id", + "near-config-utils", + "near-stdx", + "once_cell", + "primitive-types", + "secp256k1", + "serde", + "serde_json", + "subtle", + "thiserror", +] + +[[package]] +name = "near-stdx" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e1897481272eb144328abd51ca9f59b5b558e7a6dc6e2177c8c9bb18fbd818" + [[package]] name = "once_cell" version = "1.19.0" @@ -439,6 +587,12 @@ dependencies = [ "primeorder", ] +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + [[package]] name = "platforms" version = "3.3.0" @@ -483,13 +637,46 @@ dependencies = [ "elliptic-curve", ] +[[package]] +name = "primitive-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +dependencies = [ + "fixed-hash", + "uint", +] + [[package]] name = "proc-macro-crate" -version = "0.1.5" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "toml", + "proc-macro-error-attr", + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", ] [[package]] @@ -549,6 +736,12 @@ dependencies = [ "semver", ] +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + [[package]] name = "sec1" version = "0.7.3" @@ -562,6 +755,25 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "rand", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + [[package]] name = "semver" version = "1.0.22" @@ -585,7 +797,18 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", ] [[package]] @@ -599,6 +822,18 @@ dependencies = [ "digest", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" + +[[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" @@ -607,9 +842,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -617,23 +852,83 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.52" +name = "syn_derive" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" dependencies = [ + "proc-macro-error", "proc-macro2", "quote", - "unicode-ident", + "syn", ] [[package]] -name = "toml" -version = "0.5.11" +name = "thiserror" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ - "serde", + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", ] [[package]] @@ -642,6 +937,18 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[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 = "unicode-ident" version = "1.0.12" @@ -670,6 +977,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "x25519-dalek" version = "2.0.1" @@ -697,5 +1013,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn", ] diff --git a/infra/scripts/generate_cipher_keys/Cargo.toml b/infra/scripts/generate_cipher_and_sign_keys/Cargo.toml similarity index 73% rename from infra/scripts/generate_cipher_keys/Cargo.toml rename to infra/scripts/generate_cipher_and_sign_keys/Cargo.toml index aedd1ac6e..cd29d6ac5 100644 --- a/infra/scripts/generate_cipher_keys/Cargo.toml +++ b/infra/scripts/generate_cipher_and_sign_keys/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] hex = "0.4.3" -mpc-keys = { path = "../../../keys" } +near-crypto = "0.23" +mpc-keys = { path = "../../../chain-signatures/keys" } [workspace] \ No newline at end of file diff --git a/infra/scripts/generate_cipher_keys/src/main.rs b/infra/scripts/generate_cipher_and_sign_keys/src/main.rs similarity index 55% rename from infra/scripts/generate_cipher_keys/src/main.rs rename to infra/scripts/generate_cipher_and_sign_keys/src/main.rs index 550b8d263..77e6478da 100644 --- a/infra/scripts/generate_cipher_keys/src/main.rs +++ b/infra/scripts/generate_cipher_and_sign_keys/src/main.rs @@ -6,4 +6,8 @@ fn main() { let cipher_sk = hex::encode(cipher_sk.to_bytes()); println!("cipher public key: {}", cipher_pk); println!("cipher private key: {}", cipher_sk); + let sign_sk = near_crypto::SecretKey::from_random(near_crypto::KeyType::ED25519); + let sign_pk = sign_sk.public_key(); + println!("sign public key sign_pk: {}", sign_pk); + println!("sign secret key sign_sk: {}", sign_sk); } diff --git a/integration-tests/chain-signatures/Cargo.lock b/integration-tests/chain-signatures/Cargo.lock index 8363c3b33..ebac5c37f 100644 --- a/integration-tests/chain-signatures/Cargo.lock +++ b/integration-tests/chain-signatures/Cargo.lock @@ -3989,6 +3989,7 @@ dependencies = [ "hex 0.4.3", "hyper", "k256", + "lazy_static", "mpc-contract", "mpc-keys", "mpc-recovery-node", diff --git a/integration-tests/chain-signatures/Cargo.toml b/integration-tests/chain-signatures/Cargo.toml index 843498f4e..8b35380e6 100644 --- a/integration-tests/chain-signatures/Cargo.toml +++ b/integration-tests/chain-signatures/Cargo.toml @@ -16,6 +16,7 @@ hex = "0.4.3" hyper = { version = "0.14", features = ["full"] } once_cell = "1" rand = "0.7" +reqwest = "0.11.16" serde = "1" serde_json = "1" testcontainers = { version = "0.15", features = ["experimental"] } @@ -46,10 +47,10 @@ mpc-contract = { path = "../../chain-signatures/contract" } mpc-keys = { path = "../../chain-signatures/keys" } mpc-recovery-node = { path = "../../chain-signatures/node" } clap = { version = "4.5.4", features = ["derive"] } +lazy_static = "1.4.0" [dev-dependencies] backon = "0.4" -reqwest = "0.11.16" test-log = { version = "0.2.12", features = ["log", "trace"] } # crypto dependencies diff --git a/integration-tests/chain-signatures/src/containers.rs b/integration-tests/chain-signatures/src/containers.rs index 63275a103..86c66fbba 100644 --- a/integration-tests/chain-signatures/src/containers.rs +++ b/integration-tests/chain-signatures/src/containers.rs @@ -1,12 +1,15 @@ -use super::{local::NodeConfig, MultichainConfig}; -use anyhow::anyhow; +use super::{local::NodeConfig, utils, MultichainConfig}; +use anyhow::{anyhow, Context}; +use async_process::Child; use bollard::exec::CreateExecOptions; use bollard::{container::LogsOptions, network::CreateNetworkOptions, service::Ipam, Docker}; use futures::{lock::Mutex, StreamExt}; use mpc_keys::hpke; use near_workspaces::AccountId; use once_cell::sync::Lazy; +use serde_json::json; use testcontainers::clients::Cli; +use testcontainers::core::Port; use testcontainers::Image; use testcontainers::{ core::{ExecCommand, WaitFor}, @@ -45,7 +48,8 @@ impl<'a> Node<'a> { near_crypto::SecretKey::from_seed(near_crypto::KeyType::ED25519, "integration-test"); let sign_pk = sign_sk.public_key(); let storage_options = ctx.storage_options.clone(); - let near_rpc = ctx.lake_indexer.rpc_host_address.clone(); + // Use proxied address to mock slow, congested or unstable rpc connection + let near_rpc = ctx.lake_indexer.rpc_host_address_proxied.clone(); let mpc_contract_id = ctx.mpc_contract.id().clone(); let indexer_options = mpc_recovery_node::indexer::Options { s3_bucket: ctx.localstack.s3_bucket.clone(), @@ -130,7 +134,7 @@ impl<'a> Node<'a> { let account_id = config.account_id; let account_sk = config.account_sk; let storage_options = ctx.storage_options.clone(); - let near_rpc = ctx.lake_indexer.rpc_host_address.clone(); + let near_rpc = ctx.lake_indexer.rpc_host_address_proxied.clone(); let mpc_contract_id = ctx.mpc_contract.id().clone(); let indexer_options = mpc_recovery_node::indexer::Options { s3_bucket: ctx.localstack.s3_bucket.clone(), @@ -287,11 +291,93 @@ pub struct LakeIndexer<'a> { pub region: String, pub rpc_address: String, pub rpc_host_address: String, + pub rpc_host_address_proxied: String, + // Toxi Server is only used in network traffic originated from Lake Indexer + // to simulate high load and slowness etc. in Lake Indexer + // Child process is used for proxy host (local node) to container + pub toxi_server_process: Child, + // Container toxi server is used for proxy container to container + pub toxi_server_container: Container<'a, GenericImage>, } impl<'a> LakeIndexer<'a> { pub const CONTAINER_RPC_PORT: u16 = 3030; + pub const S3_PORT_PROXIED: u16 = 4566; + pub const S3_ADDRESS_PROXIED: &'static str = "127.0.0.1:4566"; + pub const TOXI_SERVER_PROCESS_PORT: u16 = 8474; + pub const TOXI_SERVER_EXPOSE_PORT: u16 = 8475; + pub const TOXI_SERVER_PROCESS_ADDRESS: &'static str = "http://127.0.0.1:8474"; + pub const TOXI_SERVER_EXPOSE_ADDRESS: &'static str = "http://127.0.0.1:8475"; + + async fn spin_up_toxi_server_process() -> anyhow::Result { + let toxi_server = async_process::Command::new("toxiproxy-server") + .kill_on_drop(true) + .spawn() + .with_context(|| "failed to run toxiproxy-server")?; + utils::ping_until_ok( + &format!("{}/version", Self::TOXI_SERVER_PROCESS_ADDRESS), + 10, + ) + .await?; + Ok(toxi_server) + } + + async fn spin_up_toxi_server_container( + docker_client: &'a DockerClient, + network: &str, + ) -> anyhow::Result> { + let image = GenericImage::new("ghcr.io/shopify/toxiproxy", "2.9.0") + .with_exposed_port(Self::CONTAINER_RPC_PORT); + let image: RunnableImage = image.into(); + let image = image.with_network(network).with_mapped_port(Port { + local: Self::TOXI_SERVER_EXPOSE_PORT, + internal: Self::TOXI_SERVER_PROCESS_PORT, + }); + let container = docker_client.cli.run(image); + container.exec(ExecCommand { + cmd: format!("bash -c 'while [[ \"$(curl -s -o /dev/null -w ''%{{http_code}}'' localhost:{}/version)\" != \"200\" ]]; do sleep 1; done'", Self::TOXI_SERVER_PROCESS_PORT), + ready_conditions: vec![WaitFor::message_on_stdout("version")] + }); + + Ok(container) + } + + // Populate a new proxy in toxi proxy server. It proxies all traffic originated from `listen` + // to `upstream`. The proxy can be configured later (adding latency etc.) given the `name` + // `listen` and `upstream` must in format `host:port` since toxiproxy operates on tcp level + // host = true, proxy between a host client request host/container server + // host = false, proxy between a container client to a container server + // With current docker setup, container client cannot request host server + async fn populate_proxy( + name: &str, + host: bool, + listen: &str, + upstream: &str, + ) -> anyhow::Result<()> { + let toxiproxy_client = reqwest::Client::default(); + let proxies = json!([{ + "name": name, + "listen": listen, + "upstream": upstream + }]); + let proxies_json = serde_json::to_string(&proxies).unwrap(); + toxiproxy_client + .post(format!( + "{}/populate", + if host { + Self::TOXI_SERVER_PROCESS_ADDRESS + } else { + Self::TOXI_SERVER_EXPOSE_ADDRESS + } + )) + .header("Content-Type", "application/json") + .body(proxies_json) + .send() + .await?; + Ok(()) + } + pub async fn run( docker_client: &'a DockerClient, network: &str, @@ -299,9 +385,35 @@ impl<'a> LakeIndexer<'a> { bucket_name: String, region: String, ) -> anyhow::Result> { + tracing::info!("initializing toxi proxy servers"); + let toxi_server_process = Self::spin_up_toxi_server_process().await?; + let toxi_server_container = + Self::spin_up_toxi_server_container(docker_client, network).await?; + let s3_address_without_http = &s3_address[7..]; + let toxi_server_container_address = docker_client + .get_network_ip_address(&toxi_server_container, network) + .await?; + let s3_address_proxied = format!( + "{}:{}", + &toxi_server_container_address, + Self::S3_PORT_PROXIED + ); tracing::info!( - network, s3_address, + s3_address_proxied, + "Proxy S3 access from Lake Indexer" + ); + Self::populate_proxy( + "lake-s3", + false, + &s3_address_proxied, + s3_address_without_http, + ) + .await?; + + tracing::info!( + network, + s3_address_proxied, bucket_name, region, "running NEAR Lake Indexer container..." @@ -316,7 +428,7 @@ impl<'a> LakeIndexer<'a> { image, vec![ "--endpoint".to_string(), - s3_address.to_string(), + format!("http://{}", s3_address_proxied), "--bucket".to_string(), bucket_name.clone(), "--region".to_string(), @@ -334,12 +446,28 @@ impl<'a> LakeIndexer<'a> { let rpc_address = format!("http://{}:{}", address, Self::CONTAINER_RPC_PORT); let rpc_host_port = container.get_host_port_ipv4(Self::CONTAINER_RPC_PORT); let rpc_host_address = format!("http://127.0.0.1:{rpc_host_port}"); + let rpc_port_proxied = utils::pick_unused_port().await?; + let rpc_host_address_proxied = format!("http://127.0.0.1:{rpc_port_proxied}"); + + tracing::info!( + "Proxy Indexer's RPC address from {} to {}", + rpc_host_address, + rpc_host_address_proxied + ); + Self::populate_proxy( + "lake-rpc", + true, + &format!("127.0.0.1:{}", rpc_port_proxied), + &format!("127.0.0.1:{}", rpc_host_port), + ) + .await?; tracing::info!( bucket_name, region, rpc_address, rpc_host_address, + rpc_host_address_proxied, "NEAR Lake Indexer container is running" ); Ok(LakeIndexer { @@ -348,6 +476,9 @@ impl<'a> LakeIndexer<'a> { region, rpc_address, rpc_host_address, + rpc_host_address_proxied, + toxi_server_process, + toxi_server_container, }) } } diff --git a/integration-tests/chain-signatures/src/lib.rs b/integration-tests/chain-signatures/src/lib.rs index 807ca547a..7d403ad4d 100644 --- a/integration-tests/chain-signatures/src/lib.rs +++ b/integration-tests/chain-signatures/src/lib.rs @@ -473,6 +473,8 @@ pub async fn initialize_lake_indexer<'a>( tracing::info!("initializing sandbox worker"); let worker = near_workspaces::sandbox() + // use not proxied rpc address because workspace is used in setup (create dev account, deploy + // contract which we can assume succeed .rpc_addr(&lake_indexer.rpc_host_address) .validator_key(ValidatorKey::Known( validator_key.account_id.to_string().parse()?, diff --git a/integration-tests/chain-signatures/src/local.rs b/integration-tests/chain-signatures/src/local.rs index 92ae63cc2..fadebfcbd 100644 --- a/integration-tests/chain-signatures/src/local.rs +++ b/integration-tests/chain-signatures/src/local.rs @@ -46,7 +46,7 @@ impl Node { s3_url: Some(ctx.localstack.s3_host_address.clone()), start_block_height: 0, }; - let near_rpc = ctx.lake_indexer.rpc_host_address.clone(); + let near_rpc = ctx.lake_indexer.rpc_host_address_proxied.clone(); let mpc_contract_id = ctx.mpc_contract.id().clone(); let cli = mpc_recovery_node::cli::Cli::Start { near_rpc: near_rpc.clone(), @@ -104,7 +104,7 @@ impl Node { }; let sign_sk = near_crypto::SecretKey::from_seed(near_crypto::KeyType::ED25519, "integration-test"); - let near_rpc = ctx.lake_indexer.rpc_host_address.clone(); + let near_rpc = ctx.lake_indexer.rpc_host_address_proxied.clone(); let mpc_contract_id = ctx.mpc_contract.id().clone(); let cli = mpc_recovery_node::cli::Cli::Start { near_rpc: near_rpc.clone(), diff --git a/integration-tests/chain-signatures/tests/actions/mod.rs b/integration-tests/chain-signatures/tests/actions/mod.rs index 92319ef20..8aed9d6f5 100644 --- a/integration-tests/chain-signatures/tests/actions/mod.rs +++ b/integration-tests/chain-signatures/tests/actions/mod.rs @@ -29,10 +29,12 @@ use std::time::Duration; const CHAIN_ID_ETH: u64 = 31337; +use integration_tests_chain_signatures::containers::LakeIndexer; use k256::{ ecdsa::{Signature as RecoverableSignature, Signature as K256Signature}, PublicKey as K256PublicKey, }; +use serde_json::json; pub async fn request_sign( ctx: &MultichainTestContext<'_>, @@ -273,6 +275,60 @@ pub async fn single_payload_signature_production( Ok(()) } +// add one of toxic to the toxiproxy-server to make indexer rpc slow down, congested, or unstable +// available toxics and params: https://github.com/Shopify/toxiproxy?tab=readme-ov-file#toxic-fields +pub async fn add_toxic(proxy: &str, host: bool, toxic: serde_json::Value) -> anyhow::Result<()> { + let toxi_server_address = if host { + LakeIndexer::TOXI_SERVER_PROCESS_ADDRESS + } else { + LakeIndexer::TOXI_SERVER_EXPOSE_ADDRESS + }; + let toxiproxy_client = reqwest::Client::default(); + toxiproxy_client + .post(format!("{}/proxies/{}/toxics", toxi_server_address, proxy)) + .header("Content-Type", "application/json") + .body(toxic.to_string()) + .send() + .await?; + Ok(()) +} + +// Add a delay to all data going through the proxy. The delay is equal to latency +/- jitter. +pub async fn add_latency( + proxy: &str, + host: bool, + probability: f32, + latency: u32, + jitter: u32, +) -> anyhow::Result<()> { + add_toxic( + proxy, + host, + json!({ + "type": "latency", + "toxicity": probability, + "attributes": { + "latency": latency, + "jitter": jitter + } + }), + ) + .await +} + +// clear all toxics. Does not need to be called between tests since each test will drop toxiproxy-server +// Only need if you want to clear all toxics in middle of a test +#[allow(dead_code)] +pub async fn clear_toxics() -> anyhow::Result<()> { + let toxi_server_address = "http://127.0.0.1:8474"; + let toxiproxy_client = reqwest::Client::default(); + toxiproxy_client + .post(format!("{}/reset", toxi_server_address)) + .send() + .await?; + Ok(()) +} + // This code was and still is a bit of a mess. // Previously converting a Scalar to bytes reversed the bytes and converted to a Scalar. // The big_r and s values were generated using chain signatures from an older commit, therefore the signature is generated against a reversed hash. diff --git a/integration-tests/chain-signatures/tests/cases/mod.rs b/integration-tests/chain-signatures/tests/cases/mod.rs index 2b03dfecf..64a206094 100644 --- a/integration-tests/chain-signatures/tests/cases/mod.rs +++ b/integration-tests/chain-signatures/tests/cases/mod.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use crate::actions::{self, wait_for}; +use crate::actions::{self, add_latency, wait_for}; use crate::with_multichain_nodes; use crypto_shared::{self, derive_epsilon, derive_key, x_coordinate, ScalarExt}; @@ -315,3 +315,26 @@ async fn test_signature_offline_node_back_online() -> anyhow::Result<()> { }) .await } + +#[test(tokio::test)] +async fn test_lake_congestion() -> anyhow::Result<()> { + with_multichain_nodes(MultichainConfig::default(), |ctx| { + Box::pin(async move { + // Currently, with a 10+-1 latency it cannot generate enough tripplets in time + // with a 5+-1 latency it fails to wait for signature response + add_latency("lake-rpc", true, 1.0, 2_000, 200).await?; + // Also mock lake indexer in high load that it becomes slower to finish process + // sig req and write to s3 + // with a 1s latency it fails to wait for signature response in time + add_latency("lake-s3", false, 1.0, 100, 10).await?; + + let state_0 = wait_for::running_mpc(&ctx, Some(0)).await?; + assert_eq!(state_0.participants.len(), 3); + wait_for::has_at_least_triples(&ctx, 2).await?; + wait_for::has_at_least_presignatures(&ctx, 2).await?; + actions::single_signature_rogue_responder(&ctx, &state_0).await?; + Ok(()) + }) + }) + .await +} diff --git a/integration-tests/chain-signatures/tests/lib.rs b/integration-tests/chain-signatures/tests/lib.rs index 99b5477e6..5269c8bce 100644 --- a/integration-tests/chain-signatures/tests/lib.rs +++ b/integration-tests/chain-signatures/tests/lib.rs @@ -137,7 +137,8 @@ where let sk_local_path = nodes.ctx().storage_options.sk_share_local_path.clone(); let connector = JsonRpcClient::new_client(); - let jsonrpc_client = connector.connect(&nodes.ctx().lake_indexer.rpc_host_address); + // Also use proxied rpc to mock unstable when submit transaction + let jsonrpc_client = connector.connect(&nodes.ctx().lake_indexer.rpc_host_address_proxied); let rpc_client = near_fetch::Client::from_client(jsonrpc_client.clone()); let result = f(MultichainTestContext { nodes, diff --git a/mpc-recovery/README.md b/mpc-recovery/README.md index af011d188..7ab0ce9c3 100644 --- a/mpc-recovery/README.md +++ b/mpc-recovery/README.md @@ -177,7 +177,7 @@ Internally, we are identifying users by their issuer id (iss) and their unique I ### Contribute -In order to build the project, you will need to have `protoc` and `gmp` installed. Refer to your system's package manager on how to do this. +In order to build the project, you will need to have `protoc` and `gmp` installed. Refer to your system's package manager on how to do this. To run chain-signatures integration test, you will also need [toxiproxy](https://github.com/Shopify/toxiproxy). Ensure `toxiproxy-server` is in `PATH`. If you have [nix](https://nixos.org/) and [direnv](https://direnv.net/) installed, you can set up a development environment by running: