From 5faaac4ffa51f94dc840ccf8ba772c2d9d35cdd8 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 27 Nov 2024 07:57:28 +0100 Subject: [PATCH 01/31] feat(solana): <- starts this and adds a first implementation of an adapter --- packages/solana/.gitignore | 7 + packages/solana/.prettierignore | 7 + packages/solana/.prettierrc.yml | 7 + packages/solana/Anchor.toml | 18 + packages/solana/Cargo.lock | 1929 +++++++++++++++++++ packages/solana/Cargo.toml | 14 + packages/solana/migrations/deploy.ts | 12 + packages/solana/package.json | 22 + packages/solana/programs/adapter/Cargo.toml | 20 + packages/solana/programs/adapter/Xargo.toml | 2 + packages/solana/programs/adapter/src/lib.rs | 59 + packages/solana/tests/adapter.ts | 40 + packages/solana/tsconfig.json | 10 + yarn.lock | 398 +++- 14 files changed, 2498 insertions(+), 47 deletions(-) create mode 100644 packages/solana/.gitignore create mode 100644 packages/solana/.prettierignore create mode 100644 packages/solana/.prettierrc.yml create mode 100644 packages/solana/Anchor.toml create mode 100644 packages/solana/Cargo.lock create mode 100644 packages/solana/Cargo.toml create mode 100644 packages/solana/migrations/deploy.ts create mode 100644 packages/solana/package.json create mode 100644 packages/solana/programs/adapter/Cargo.toml create mode 100644 packages/solana/programs/adapter/Xargo.toml create mode 100644 packages/solana/programs/adapter/src/lib.rs create mode 100644 packages/solana/tests/adapter.ts create mode 100644 packages/solana/tsconfig.json diff --git a/packages/solana/.gitignore b/packages/solana/.gitignore new file mode 100644 index 00000000..2e0446b0 --- /dev/null +++ b/packages/solana/.gitignore @@ -0,0 +1,7 @@ +.anchor +.DS_Store +target +**/*.rs.bk +node_modules +test-ledger +.yarn diff --git a/packages/solana/.prettierignore b/packages/solana/.prettierignore new file mode 100644 index 00000000..41425834 --- /dev/null +++ b/packages/solana/.prettierignore @@ -0,0 +1,7 @@ +.anchor +.DS_Store +target +node_modules +dist +build +test-ledger diff --git a/packages/solana/.prettierrc.yml b/packages/solana/.prettierrc.yml new file mode 100644 index 00000000..e9bada2e --- /dev/null +++ b/packages/solana/.prettierrc.yml @@ -0,0 +1,7 @@ +bracketSpacing: true +printWidth: 120 +proseWrap: "always" +singleQuote: false +tabWidth: 2 +trailingComma: "all" +semi: false diff --git a/packages/solana/Anchor.toml b/packages/solana/Anchor.toml new file mode 100644 index 00000000..7fabe64c --- /dev/null +++ b/packages/solana/Anchor.toml @@ -0,0 +1,18 @@ +[toolchain] + +[features] +resolution = true +skip-lint = false + +[programs.localnet] +solana = "4VFxPo4BF53PkVFBFjCQBFUn8bCxZZm6Dc2VgrJ5HXS8" + +[registry] +url = "https://api.apr.dev" + +[provider] +cluster = "Localnet" +wallet = "~/.config/solana/id.json" + +[scripts] +test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock new file mode 100644 index 00000000..fd6236c5 --- /dev/null +++ b/packages/solana/Cargo.lock @@ -0,0 +1,1929 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adapters" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anchor-attribute-access-control" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47fe28365b33e8334dd70ae2f34a43892363012fe239cf37d2ee91693575b1f8" +dependencies = [ + "anchor-syn", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-account" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c288d496168268d198d9b53ee9f4f9d260a55ba4df9877ea1d4486ad6109e0f" +dependencies = [ + "anchor-syn", + "bs58 0.5.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-constant" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b77b6948d0eeaaa129ce79eea5bbbb9937375a9241d909ca8fb9e006bb6e90" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-error" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d20bb569c5a557c86101b944721d865e1fd0a4c67c381d31a44a84f07f84828" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-event" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cebd8d0671a3a9dc3160c48598d652c34c77de6be4d44345b8b514323284d57" +dependencies = [ + "anchor-syn", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-program" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb2a5eb0860e661ab31aff7bb5e0288357b176380e985bade4ccb395981b42d" +dependencies = [ + "anchor-lang-idl", + "anchor-syn", + "anyhow", + "bs58 0.5.1", + "heck", + "proc-macro2", + "quote", + "serde_json", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-accounts" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04368b5abef4266250ca8d1d12f4dff860242681e4ec22b885dcfe354fd35aa1" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-serde" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0bb0e0911ad4a70cab880cdd6287fe1e880a1a9d8e4e6defa8e9044b9796a6c" +dependencies = [ + "anchor-syn", + "borsh-derive-internal 0.10.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-space" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef415ff156dc82e9ecb943189b0cb241b3a6bfc26a180234dc21bd3ef3ce0cb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-lang" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6620c9486d9d36a4389cab5e37dc34a42ed0bfaa62e6a75a2999ce98f8f2e373" +dependencies = [ + "anchor-attribute-access-control", + "anchor-attribute-account", + "anchor-attribute-constant", + "anchor-attribute-error", + "anchor-attribute-event", + "anchor-attribute-program", + "anchor-derive-accounts", + "anchor-derive-serde", + "anchor-derive-space", + "anchor-lang-idl", + "arrayref", + "base64 0.21.7", + "bincode", + "borsh 0.10.4", + "bytemuck", + "getrandom 0.2.15", + "solana-program", + "thiserror", +] + +[[package]] +name = "anchor-lang-idl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31cf97b4e6f7d6144a05e435660fcf757dbc3446d38d0e2b851d11ed13625bba" +dependencies = [ + "anchor-lang-idl-spec", + "anyhow", + "heck", + "regex", + "serde", + "serde_json", + "sha2 0.10.8", +] + +[[package]] +name = "anchor-lang-idl-spec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdf143115440fe621bdac3a29a1f7472e09f6cd82b2aa569429a0c13f103838" +dependencies = [ + "anyhow", + "serde", +] + +[[package]] +name = "anchor-syn" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f99daacb53b55cfd37ce14d6c9905929721137fd4c67bbab44a19802aecb622f" +dependencies = [ + "anyhow", + "bs58 0.5.1", + "cargo_toml", + "heck", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "syn 1.0.109", + "thiserror", +] + +[[package]] +name = "anyhow" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blake3" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.7", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive 0.9.3", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" +dependencies = [ + "borsh-derive 0.10.4", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" +dependencies = [ + "borsh-derive 1.5.3", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal 0.9.3", + "borsh-schema-derive-internal 0.9.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" +dependencies = [ + "borsh-derive-internal 0.10.4", + "borsh-schema-derive-internal 0.10.4", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" +dependencies = [ + "once_cell", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[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", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "bytemuck" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cargo_toml" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" +dependencies = [ + "serde", + "toml 0.8.19", +] + +[[package]] +name = "cc" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[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 = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "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 = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "serde", + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.11", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[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 = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "rayon", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.165" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb4d3d38eab6c5239a362fa8bae48c03baf980a6e7079f063942d563ef3533e" + +[[package]] +name = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "light-poseidon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +dependencies = [ + "ark-bn254", + "ark-ff", + "num-bigint", + "thiserror", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "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]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "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]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[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]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "solana-frozen-abi" +version = "1.18.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ab2c30c15311b511c0d1151e4ab6bc9a3e080a37e7c6e7c2d96f5784cf9434" +dependencies = [ + "block-buffer 0.10.4", + "bs58 0.4.0", + "bv", + "either", + "generic-array", + "im", + "lazy_static", + "log", + "memmap2", + "rustc_version", + "serde", + "serde_bytes", + "serde_derive", + "sha2 0.10.8", + "solana-frozen-abi-macro", + "subtle", + "thiserror", +] + +[[package]] +name = "solana-frozen-abi-macro" +version = "1.18.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c142f779c3633ac83c84d04ff06c70e1f558c876f13358bed77ba629c7417932" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.89", +] + +[[package]] +name = "solana-program" +version = "1.18.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c10f4588cefd716b24a1a40dd32c278e43a560ab8ce4de6b5805c9d113afdfa1" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "base64 0.21.7", + "bincode", + "bitflags", + "blake3", + "borsh 0.10.4", + "borsh 0.9.3", + "borsh 1.5.3", + "bs58 0.4.0", + "bv", + "bytemuck", + "cc", + "console_error_panic_hook", + "console_log", + "curve25519-dalek", + "getrandom 0.2.15", + "itertools", + "js-sys", + "lazy_static", + "libc", + "libsecp256k1", + "light-poseidon", + "log", + "memoffset", + "num-bigint", + "num-derive", + "num-traits", + "parking_lot", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "sha3", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk-macro", + "thiserror", + "tiny-bip39", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-sdk-macro" +version = "1.18.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b75d0f193a27719257af19144fdaebec0415d1c9e9226ae4bd29b791be5e9bd" +dependencies = [ + "bs58 0.4.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.89", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "tiny-bip39" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" +dependencies = [ + "anyhow", + "hmac", + "once_cell", + "pbkdf2", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[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.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.89", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "web-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +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.89", +] diff --git a/packages/solana/Cargo.toml b/packages/solana/Cargo.toml new file mode 100644 index 00000000..f3977048 --- /dev/null +++ b/packages/solana/Cargo.toml @@ -0,0 +1,14 @@ +[workspace] +members = [ + "programs/*" +] +resolver = "2" + +[profile.release] +overflow-checks = true +lto = "fat" +codegen-units = 1 +[profile.release.build-override] +opt-level = 3 +incremental = false +codegen-units = 1 diff --git a/packages/solana/migrations/deploy.ts b/packages/solana/migrations/deploy.ts new file mode 100644 index 00000000..6dafdee2 --- /dev/null +++ b/packages/solana/migrations/deploy.ts @@ -0,0 +1,12 @@ +// Migrations are an early feature. Currently, they're nothing more than this +// single deploy script that's invoked from the CLI, injecting a provider +// configured from the workspace's Anchor.toml. + +const anchor = require("@coral-xyz/anchor") + +module.exports = async function (provider) { + // Configure client to use the provider. + anchor.setProvider(provider) + + // Add your deploy script here. +} diff --git a/packages/solana/package.json b/packages/solana/package.json new file mode 100644 index 00000000..31a0ff57 --- /dev/null +++ b/packages/solana/package.json @@ -0,0 +1,22 @@ +{ + "name": "@gnosis/hashi-solana", + "version": "0.0.1", + "private": true, + "scripts": { + "prettier:check": "prettier --check \"**/*.{js,json,md,ts,yml}\"", + "prettier:write": "prettier --write \"**/*.{js,json,md,ts,yml}\"" + }, + "dependencies": { + "@coral-xyz/anchor": "^0.30.1" + }, + "devDependencies": { + "chai": "^4.3.4", + "mocha": "^9.0.3", + "ts-mocha": "^10.0.0", + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "typescript": "^4.3.5", + "prettier": "^2.6.2" + } +} diff --git a/packages/solana/programs/adapter/Cargo.toml b/packages/solana/programs/adapter/Cargo.toml new file mode 100644 index 00000000..432d03d3 --- /dev/null +++ b/packages/solana/programs/adapter/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "adapters" +version = "0.1.0" +description = "Hashi Adapter" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] +name = "adapters" + +[features] +default = [] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build"] + +[dependencies] +anchor-lang = { version = "0.30.1", features = ["init-if-needed"] } diff --git a/packages/solana/programs/adapter/Xargo.toml b/packages/solana/programs/adapter/Xargo.toml new file mode 100644 index 00000000..475fb71e --- /dev/null +++ b/packages/solana/programs/adapter/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/packages/solana/programs/adapter/src/lib.rs b/packages/solana/programs/adapter/src/lib.rs new file mode 100644 index 00000000..bcaa8197 --- /dev/null +++ b/packages/solana/programs/adapter/src/lib.rs @@ -0,0 +1,59 @@ +use anchor_lang::prelude::*; + +declare_id!("77amskJVh59Y7uV5XCxU47rXuHLygXhY7F3PKa6NEUyV"); + +#[program] +pub mod adapter { + use super::*; + + pub fn store_hash( + ctx: Context, + domain: [u8; 32], + id: [u8; 32], + hash: [u8; 32], + ) -> Result<()> { + let hash_account = &mut ctx.accounts.hash_account; + + hash_account.domain = domain; + hash_account.id = id; + hash_account.hash = hash; + + emit!(HashStored { domain, id, hash }); + + Ok(()) + } +} + +#[account] +pub struct HashAccount { + pub domain: [u8; 32], + pub id: [u8; 32], + pub hash: [u8; 32], +} + +#[derive(Accounts)] +#[instruction(domain: [u8; 32], id: [u8; 32])] +pub struct StoreHash<'info> { + #[account( + init_if_needed, + payer = user, + space = 8 + 32 + 32 + 32, // discriminator + domain + id + hash + seeds = [ + b"hash_account".as_ref(), + &domain, + &id + ], + bump, + )] + pub hash_account: Account<'info, HashAccount>, + #[account(mut)] + pub user: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[event] +pub struct HashStored { + pub domain: [u8; 32], + pub id: [u8; 32], + pub hash: [u8; 32], +} diff --git a/packages/solana/tests/adapter.ts b/packages/solana/tests/adapter.ts new file mode 100644 index 00000000..3a1a5907 --- /dev/null +++ b/packages/solana/tests/adapter.ts @@ -0,0 +1,40 @@ +import * as anchor from "@coral-xyz/anchor" +import { Program } from "@coral-xyz/anchor" +import { Adapter } from "../target/types/adapter" +import { SystemProgram, PublicKey } from "@solana/web3.js" +import { expect } from "chai" + +const DOMAIN = 1 + +const intToBytes32Buff = (_num: number) => Buffer.from(_num.toString(16).padStart(64, "0"), "hex") + +describe("adapter", () => { + const provider = anchor.AnchorProvider.local() + anchor.setProvider(provider) + + const adapter = anchor.workspace.Adapter as Program + + it("should store an hash", async () => { + const id = 1 + const hash = Array.from( + Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), + ) + + const [hashAccountPDA] = await PublicKey.findProgramAddressSync( + [Buffer.from("hash_account", "utf-8"), intToBytes32Buff(DOMAIN), intToBytes32Buff(id)], + adapter.programId, + ) + + await adapter.methods + .storeHash(intToBytes32Buff(DOMAIN), intToBytes32Buff(id), hash) + .accounts({ + hashAccount: hashAccountPDA, + user: provider.wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .rpc() + + const hashAccount = await adapter.account.hashAccount.fetch(hashAccountPDA) + expect(hashAccount.hash).to.be.deep.eq(hash) + }) +}) diff --git a/packages/solana/tsconfig.json b/packages/solana/tsconfig.json new file mode 100644 index 00000000..cd5d2e3d --- /dev/null +++ b/packages/solana/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "commonjs", + "target": "es6", + "esModuleInterop": true + } +} diff --git a/yarn.lock b/yarn.lock index e379e0cd..53391635 100644 --- a/yarn.lock +++ b/yarn.lock @@ -297,6 +297,40 @@ resolved "https://registry.yarnpkg.com/@connext/interfaces/-/interfaces-2.0.0.tgz#17f27a516315e40a440c3ef34db83834ad51917f" integrity sha512-1dYh5T0Zx6zVvLWDHRRUuXZxTGLXeqefDK/zUQyNYQMmPWRBzA967wK0mtrU6drJq4VkO2gZ5QFE63mMDEz8TQ== +"@coral-xyz/anchor-errors@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor-errors/-/anchor-errors-0.30.1.tgz#bdfd3a353131345244546876eb4afc0e125bec30" + integrity sha512-9Mkradf5yS5xiLWrl9WrpjqOrAV+/W2RQHDlbnAZBivoGpOs1ECjoDCkVk4aRG8ZdiFiB8zQEVlxf+8fKkmSfQ== + +"@coral-xyz/anchor@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.1.tgz#17f3e9134c28cd0ea83574c6bab4e410bcecec5d" + integrity sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ== + dependencies: + "@coral-xyz/anchor-errors" "^0.30.1" + "@coral-xyz/borsh" "^0.30.1" + "@noble/hashes" "^1.3.1" + "@solana/web3.js" "^1.68.0" + bn.js "^5.1.2" + bs58 "^4.0.1" + buffer-layout "^1.2.2" + camelcase "^6.3.0" + cross-fetch "^3.1.5" + crypto-hash "^1.3.0" + eventemitter3 "^4.0.7" + pako "^2.0.3" + snake-case "^3.0.4" + superstruct "^0.15.4" + toml "^3.0.0" + +"@coral-xyz/borsh@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.30.1.tgz#869d8833abe65685c72e9199b8688477a4f6b0e3" + integrity sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ== + dependencies: + bn.js "^5.1.2" + buffer-layout "^1.2.0" + "@cosmjs/encoding@^0.31.3": version "0.31.3" resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.31.3.tgz#2519d9c9ae48368424971f253775c4580b54c5aa" @@ -953,6 +987,11 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== +"@noble/hashes@^1.3.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== + "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": version "1.3.3" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" @@ -1545,6 +1584,27 @@ dependencies: buffer "~6.0.3" +"@solana/web3.js@^1.68.0": + version "1.95.5" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.95.5.tgz#ba70da4c205c64249ed94369fe2d617c0347cd85" + integrity sha512-hU9cBrbg1z6gEjLH9vwIckGBVB78Ijm0iZFNk4ocm5OD82piPwuk3MeQ1rfiKD9YQtr95krrcaopb49EmQJlRg== + dependencies: + "@babel/runtime" "^7.25.0" + "@noble/curves" "^1.4.2" + "@noble/hashes" "^1.4.0" + "@solana/buffer-layout" "^4.0.1" + agentkeepalive "^4.5.0" + bigint-buffer "^1.1.5" + bn.js "^5.2.1" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.3" + fast-stable-stringify "^1.0.0" + jayson "^4.1.1" + node-fetch "^2.7.0" + rpc-websockets "^9.0.2" + superstruct "^2.0.2" + "@solana/web3.js@^1.78.0": version "1.95.3" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.95.3.tgz#70b5f4d76823f56b5af6403da51125fffeb65ff3" @@ -1666,6 +1726,11 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.19.tgz#14519f437361d41e84102ed3fbc922ddace3e228" integrity sha512-2hHHvQBVE2FiSK4eN0Br6snX9MtolHaTo/batnLjlGRhoQzlCL61iVpxoqO7SfFyOw+P/pwv+0zNHzKoGWz9Cw== +"@types/chai@^4.3.0": + version "4.3.20" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.20.tgz#cb291577ed342ca92600430841a00329ba05cecc" + integrity sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ== + "@types/concat-stream@^1.6.0": version "1.6.1" resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" @@ -1725,6 +1790,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + "@types/lru-cache@^5.1.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" @@ -1757,6 +1827,11 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.8.tgz#a7eff5816e070c3b4d803f1d3cd780c4e42934a1" integrity sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw== +"@types/mocha@^9.0.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + "@types/node-cron@^3.0.9": version "3.0.11" resolved "https://registry.yarnpkg.com/@types/node-cron/-/node-cron-3.0.11.tgz#70b7131f65038ae63cfe841354c8aba363632344" @@ -2105,6 +2180,11 @@ "@typescript-eslint/types" "6.21.0" eslint-visitor-keys "^3.4.1" +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" @@ -2254,6 +2334,11 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + ansi-colors@^4.1.1, ansi-colors@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" @@ -2355,7 +2440,7 @@ array-uniq@1.0.3: resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== -arrify@^1.0.1: +arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== @@ -2565,7 +2650,7 @@ browser-level@^1.0.1: module-error "^1.0.2" run-parallel-limit "^1.1.0" -browser-stdout@^1.3.1: +browser-stdout@1.3.1, browser-stdout@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== @@ -2603,11 +2688,16 @@ bson@^6.4.0: resolved "https://registry.yarnpkg.com/bson/-/bson-6.8.0.tgz#5063c41ba2437c2b8ff851b50d9e36cb7aaa7525" integrity sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ== -buffer-from@^1.0.0: +buffer-from@^1.0.0, buffer-from@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer-layout@^1.2.0, buffer-layout@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/buffer-layout/-/buffer-layout-1.2.2.tgz#b9814e7c7235783085f9ca4966a0cfff112259d5" + integrity sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA== + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -2677,7 +2767,7 @@ camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: +camelcase@^6.0.0, camelcase@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -2760,6 +2850,21 @@ check-error@^1.0.2, check-error@^1.0.3: dependencies: get-func-name "^2.0.2" +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" @@ -3069,6 +3174,13 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -3083,6 +3195,11 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== +crypto-hash@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247" + integrity sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg== + dargs@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" @@ -3107,6 +3224,13 @@ debug@4, debug@^4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug dependencies: ms "^2.1.3" +debug@4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + decamelize-keys@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" @@ -3171,6 +3295,16 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^3.1.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -3202,6 +3336,14 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -3328,16 +3470,16 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" @@ -3647,6 +3789,11 @@ ethjs-util@0.1.6, ethjs-util@^0.1.6: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" +eventemitter3@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + eventemitter3@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" @@ -3814,6 +3961,14 @@ find-replace@^3.0.0: dependencies: array-back "^3.0.1" +find-up@5.0.0, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -3829,14 +3984,6 @@ find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - find-yarn-workspace-root@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" @@ -4200,6 +4347,11 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + handlebars@^4.0.1: version "4.7.8" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" @@ -4371,7 +4523,7 @@ hasown@^2.0.0, hasown@^2.0.2: dependencies: function-bind "^1.1.2" -he@^1.2.0: +he@1.2.0, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -4734,7 +4886,7 @@ js-yaml@3.x: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: +js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -4786,6 +4938,13 @@ json-stringify-safe@^5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -4999,7 +5158,7 @@ lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@^4.1.0: +log-symbols@4.1.0, log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -5026,6 +5185,13 @@ loupe@^2.3.6: dependencies: get-func-name "^2.0.1" +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + lru-cache@10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" @@ -5207,6 +5373,13 @@ minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" +minimatch@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" + integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== + dependencies: + brace-expansion "^1.1.7" + minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -5237,7 +5410,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -5287,6 +5460,36 @@ mocha@^10.0.0, mocha@^10.2.0: yargs-parser "^20.2.9" yargs-unparser "^2.0.0" +mocha@^9.0.3: + version "9.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" + integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.3" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "4.2.1" + ms "2.1.3" + nanoid "3.3.1" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + workerpool "6.2.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + module-error@^1.0.1, module-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" @@ -5314,6 +5517,11 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" @@ -5328,6 +5536,11 @@ murmur-128@^0.2.1: fmix "^0.1.0" imul "^1.0.0" +nanoid@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== + napi-macros@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.2.2.tgz#817fef20c3e0e40a963fbf7b37d1600bd0201044" @@ -5353,6 +5566,14 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" @@ -5365,7 +5586,7 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.7.0: +node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -5599,6 +5820,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +pako@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -5743,7 +5969,7 @@ prettier-plugin-solidity@^1.0.0, prettier-plugin-solidity@^1.3.1, prettier-plugi "@solidity-parser/parser" "^0.18.0" semver "^7.5.4" -prettier@^2.1.2, prettier@^2.3.1, prettier@^2.8.3, prettier@^2.8.7: +prettier@^2.1.2, prettier@^2.3.1, prettier@^2.6.2, prettier@^2.8.3, prettier@^2.8.7: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== @@ -6162,6 +6388,13 @@ send@0.19.0: range-parser "~1.2.1" statuses "2.0.1" +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + serialize-javascript@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" @@ -6286,6 +6519,14 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -6376,7 +6617,7 @@ solidity-rlp@2.0.8: resolved "https://registry.yarnpkg.com/solidity-rlp/-/solidity-rlp-2.0.8.tgz#1548370b690ef06dbb62af06b7675bc86b19bbe3" integrity sha512-gzYzHoFKRH1ydJeCfzm3z/BvKrZGK/V9+qbOlNbBcRAYeizjCdDNhLTTE8iIJrHqsRrZRSOo+7mhbnxoBoZvJQ== -source-map-support@^0.5.13: +source-map-support@^0.5.13, source-map-support@^0.5.6: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -6508,6 +6749,11 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -6527,16 +6773,28 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +superstruct@^0.15.4: + version "0.15.5" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.5.tgz#0f0a8d3ce31313f0d84c6096cd4fa1bfdedc9dab" + integrity sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ== + superstruct@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A== +supports-color@8.1.1, supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" @@ -6558,13 +6816,6 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -6675,6 +6926,11 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +toml@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" + integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== + touch@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" @@ -6742,6 +6998,29 @@ ts-generator@^0.1.1: resolve "^1.8.1" ts-essentials "^1.0.0" +ts-mocha@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" + integrity sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw== + dependencies: + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" + ts-node@^10.8.1, ts-node@^10.9.1, ts-node@^10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" @@ -6761,6 +7040,16 @@ ts-node@^10.8.1, ts-node@^10.9.1, ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +tsconfig-paths@^3.5.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + tslib@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" @@ -6771,7 +7060,7 @@ tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.3.1, tslib@^2.6.2: +tslib@^2.0.3, tslib@^2.3.1, tslib@^2.6.2: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -6881,16 +7170,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== +typescript@^4.3.5, typescript@^4.9.3: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + "typescript@^4.6.4 || ^5.2.2", typescript@^5.2.2: version "5.6.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0" integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw== -typescript@^4.9.3: - version "4.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" - integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== - typescript@~5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" @@ -7097,6 +7386,13 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +which@2.0.2, which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + which@^1.1.1, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -7104,13 +7400,6 @@ which@^1.1.1, which@^1.3.1: dependencies: isexe "^2.0.0" -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - winston-transport@^4.7.0: version "4.7.1" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.1.tgz#52ff1bcfe452ad89991a0aaff9c3b18e7f392569" @@ -7155,6 +7444,11 @@ wordwrapjs@^4.0.0: reduce-flatten "^2.0.0" typical "^5.2.0" +workerpool@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== + workerpool@^6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" @@ -7219,6 +7513,11 @@ yaml@^2.2.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.1.tgz#c9772aacf62cb7494a95b0c4f1fb065b563db130" integrity sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q== +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20.2.9: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" @@ -7229,7 +7528,7 @@ yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs-unparser@^2.0.0: +yargs-unparser@2.0.0, yargs-unparser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== @@ -7239,7 +7538,7 @@ yargs-unparser@^2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@^16.2.0: +yargs@16.2.0, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -7270,6 +7569,11 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 9c40e5b6320b636ea3354f64536538c5b4dc7546 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 27 Nov 2024 18:17:24 +0100 Subject: [PATCH 02/31] feat(solana): starts adding hashi program --- packages/solana/Anchor.toml | 2 + packages/solana/Cargo.lock | 9 +- packages/solana/programs/adapter/Cargo.toml | 4 +- packages/solana/programs/adapter/src/lib.rs | 24 +++- packages/solana/programs/hashi/Cargo.toml | 20 ++++ packages/solana/programs/hashi/Xargo.toml | 2 + packages/solana/programs/hashi/src/lib.rs | 94 ++++++++++++++++ packages/solana/tests/adapter.ts | 12 +- packages/solana/tests/hashi.ts | 117 ++++++++++++++++++++ packages/solana/tests/utils.ts | 1 + 10 files changed, 272 insertions(+), 13 deletions(-) create mode 100644 packages/solana/programs/hashi/Cargo.toml create mode 100644 packages/solana/programs/hashi/Xargo.toml create mode 100644 packages/solana/programs/hashi/src/lib.rs create mode 100644 packages/solana/tests/hashi.ts create mode 100644 packages/solana/tests/utils.ts diff --git a/packages/solana/Anchor.toml b/packages/solana/Anchor.toml index 7fabe64c..6311454e 100644 --- a/packages/solana/Anchor.toml +++ b/packages/solana/Anchor.toml @@ -5,6 +5,8 @@ resolution = true skip-lint = false [programs.localnet] +hashi = "EyqiZf8Yt2CgVU5yPsj5e4EiGXeKrLhefWBn7CSqKPMC" +help = "EJy8wh5fqP5LYqs1mNbH2S6jxKGkP64PkXRmZgQxk9CE" solana = "4VFxPo4BF53PkVFBFjCQBFUn8bCxZZm6Dc2VgrJ5HXS8" [registry] diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index fd6236c5..c50b5ff2 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -3,7 +3,7 @@ version = 3 [[package]] -name = "adapters" +name = "adapter" version = "0.1.0" dependencies = [ "anchor-lang", @@ -847,6 +847,13 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +[[package]] +name = "hashi" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + [[package]] name = "heck" version = "0.3.3" diff --git a/packages/solana/programs/adapter/Cargo.toml b/packages/solana/programs/adapter/Cargo.toml index 432d03d3..8d344365 100644 --- a/packages/solana/programs/adapter/Cargo.toml +++ b/packages/solana/programs/adapter/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "adapters" +name = "adapter" version = "0.1.0" description = "Hashi Adapter" edition = "2021" [lib] crate-type = ["cdylib", "lib"] -name = "adapters" +name = "adapter" [features] default = [] diff --git a/packages/solana/programs/adapter/src/lib.rs b/packages/solana/programs/adapter/src/lib.rs index bcaa8197..a660bd9c 100644 --- a/packages/solana/programs/adapter/src/lib.rs +++ b/packages/solana/programs/adapter/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("77amskJVh59Y7uV5XCxU47rXuHLygXhY7F3PKa6NEUyV"); +declare_id!("E31NDsJknUaJ1VKGBCePkcZysajUqqFw5pDFAz1fFAGu"); #[program] pub mod adapter { @@ -8,17 +8,24 @@ pub mod adapter { pub fn store_hash( ctx: Context, + adapter_id: [u8; 32], domain: [u8; 32], id: [u8; 32], hash: [u8; 32], ) -> Result<()> { let hash_account = &mut ctx.accounts.hash_account; + hash_account.adapter_id = adapter_id; hash_account.domain = domain; hash_account.id = id; hash_account.hash = hash; - emit!(HashStored { domain, id, hash }); + emit!(HashStored { + adapter_id, + domain, + id, + hash + }); Ok(()) } @@ -26,20 +33,26 @@ pub mod adapter { #[account] pub struct HashAccount { + pub adapter_id: [u8; 32], pub domain: [u8; 32], pub id: [u8; 32], pub hash: [u8; 32], } +impl HashAccount { + pub const LEN: usize = 32 + 32 + 32 + 32; +} + #[derive(Accounts)] -#[instruction(domain: [u8; 32], id: [u8; 32])] +#[instruction(adapter_id: [u8; 32], domain: [u8; 32], id: [u8; 32])] pub struct StoreHash<'info> { #[account( init_if_needed, payer = user, - space = 8 + 32 + 32 + 32, // discriminator + domain + id + hash + space = 8 + HashAccount::LEN, seeds = [ - b"hash_account".as_ref(), + "hash_account".as_bytes(), + &adapter_id, &domain, &id ], @@ -53,6 +66,7 @@ pub struct StoreHash<'info> { #[event] pub struct HashStored { + pub adapter_id: [u8; 32], pub domain: [u8; 32], pub id: [u8; 32], pub hash: [u8; 32], diff --git a/packages/solana/programs/hashi/Cargo.toml b/packages/solana/programs/hashi/Cargo.toml new file mode 100644 index 00000000..2f6aa167 --- /dev/null +++ b/packages/solana/programs/hashi/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "hashi" +version = "0.1.0" +description = "Created with Anchor" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] +name = "hashi" + +[features] +default = [] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build"] + +[dependencies] +anchor-lang = "0.30.1" diff --git a/packages/solana/programs/hashi/Xargo.toml b/packages/solana/programs/hashi/Xargo.toml new file mode 100644 index 00000000..475fb71e --- /dev/null +++ b/packages/solana/programs/hashi/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/packages/solana/programs/hashi/src/lib.rs b/packages/solana/programs/hashi/src/lib.rs new file mode 100644 index 00000000..d6967982 --- /dev/null +++ b/packages/solana/programs/hashi/src/lib.rs @@ -0,0 +1,94 @@ +use anchor_lang::prelude::*; +use std::collections::HashMap; + +declare_id!("EyqiZf8Yt2CgVU5yPsj5e4EiGXeKrLhefWBn7CSqKPMC"); + +#[program] +pub mod hashi { + use super::*; + + pub fn check_hash_with_threshold_from_adapters( + ctx: Context, + adapter_ids: Vec<[u8; 32]>, + domain: [u8; 32], + id: [u8; 32], + threshold: u64, + ) -> Result<()> { + if threshold as usize > ctx.remaining_accounts.len() { + return Err(error!(ErrorCode::InvalidThreshold)); + } + + if ctx.remaining_accounts.is_empty() { + return Err(error!(ErrorCode::NoAccountsProvided)); + } + + if ctx.remaining_accounts.len() != adapter_ids.len() { + return Err(error!(ErrorCode::InvalidAdapterIdsLength)); + } + + let mut hash_counts: HashMap<[u8; 32], u32> = HashMap::new(); + + for (index, account_info) in ctx.remaining_accounts.iter().enumerate() { + let data = account_info.try_borrow_data()?; + let hash_account = + HashAccount::try_deserialize(&mut data.as_ref()).expect("Error Deserializing Data"); + + if hash_account.adapter_id != adapter_ids[index] { + return Err(error!(ErrorCode::InvalidAdapterId)); + } + + if hash_account.domain != domain { + return Err(error!(ErrorCode::InvalidDomain)); + } + + if hash_account.id != id { + return Err(error!(ErrorCode::InvalidId)); + } + + let count = hash_counts.entry(hash_account.hash).or_insert(0); + *count += 1; + } + + let mut max_count = 0; + for (hash, count) in hash_counts.iter() { + if *count > max_count { + max_count = *count; + } + } + + if max_count >= threshold as u32 { + Ok(()) + } else { + Err(error!(ErrorCode::ThresholdNotMet)) + } + } +} + +#[derive(Accounts)] +pub struct ReadHashes {} + +#[account] +pub struct HashAccount { + pub adapter_id: [u8; 32], + pub domain: [u8; 32], + pub id: [u8; 32], + pub hash: [u8; 32], +} + +#[error_code] +pub enum ErrorCode { + #[msg("The majority threshold was not met.")] + ThresholdNotMet, + #[msg("Invalid threshold: greater than the number of accounts provided.")] + InvalidThreshold, + #[msg("No accounts were provided.")] + NoAccountsProvided, + #[msg("Invalid adapter id.")] + InvalidAdapterId, + #[msg("Invalid adapter ids length.")] + InvalidAdapterIdsLength, + #[msg("Invalid domain.")] + InvalidId, + #[msg("Invalid id.")] + InvalidDomain, +} diff --git a/packages/solana/tests/adapter.ts b/packages/solana/tests/adapter.ts index 3a1a5907..869a2e5b 100644 --- a/packages/solana/tests/adapter.ts +++ b/packages/solana/tests/adapter.ts @@ -1,12 +1,14 @@ import * as anchor from "@coral-xyz/anchor" import { Program } from "@coral-xyz/anchor" -import { Adapter } from "../target/types/adapter" import { SystemProgram, PublicKey } from "@solana/web3.js" import { expect } from "chai" -const DOMAIN = 1 +import { intToBytes32Buff } from "./utils" + +import { Adapter } from "../target/types/adapter" -const intToBytes32Buff = (_num: number) => Buffer.from(_num.toString(16).padStart(64, "0"), "hex") +const DOMAIN = intToBytes32Buff(1) +const ADAPTER_ID = Buffer.from("7d540e5aca706562723c44571ddc1a40653d3a88dd314aa64cd44dbca1267c56", "hex") // "mock-adapter" describe("adapter", () => { const provider = anchor.AnchorProvider.local() @@ -21,12 +23,12 @@ describe("adapter", () => { ) const [hashAccountPDA] = await PublicKey.findProgramAddressSync( - [Buffer.from("hash_account", "utf-8"), intToBytes32Buff(DOMAIN), intToBytes32Buff(id)], + [Buffer.from("hash_account", "utf-8"), ADAPTER_ID, DOMAIN, intToBytes32Buff(id)], adapter.programId, ) await adapter.methods - .storeHash(intToBytes32Buff(DOMAIN), intToBytes32Buff(id), hash) + .storeHash(ADAPTER_ID, DOMAIN, intToBytes32Buff(id), hash) .accounts({ hashAccount: hashAccountPDA, user: provider.wallet.publicKey, diff --git a/packages/solana/tests/hashi.ts b/packages/solana/tests/hashi.ts new file mode 100644 index 00000000..8dc428f4 --- /dev/null +++ b/packages/solana/tests/hashi.ts @@ -0,0 +1,117 @@ +import * as anchor from "@coral-xyz/anchor" +import { Program } from "@coral-xyz/anchor" +import { SystemProgram, PublicKey } from "@solana/web3.js" +import { expect } from "chai" + +import { intToBytes32Buff } from "./utils" + +import { Hashi } from "../target/types/hashi" +import { Adapter } from "../target/types/adapter" + +const DOMAIN = intToBytes32Buff(1) +const ADAPTER_ID_1 = Buffer.from("2244e849e1d0cb22ba71f9ef4b933b7f3f72f13595966f9adc6e289501941c8d", "hex") // sha256("mock-adapter-1") +const ADAPTER_ID_2 = Buffer.from("77038193f4439e5312f8cf018ccc79007c42753aadefa68598e0282840e2f2b5", "hex") // sha256("mock-adapter-2") +const ADAPTER_ID_3 = Buffer.from("feb487914b67a80f0dda2a37b1f2da9086dbf67c1b0676b2f9ee61a877035e63", "hex") // sha256("mock-adapter-3") +const ADAPTER_IDS = [ADAPTER_ID_1, ADAPTER_ID_2, ADAPTER_ID_3] + +describe("hashi", () => { + const provider = anchor.AnchorProvider.local() + anchor.setProvider(provider) + + const hashi = anchor.workspace.Hashi as Program + const adapter = anchor.workspace.Adapter as Program + + it("should not fail if the majority of adapters agree on an hash", async () => { + const threshold = 2 + const id = 1 + const hashes = [ + Array.from( + Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), + ), + Array.from( + Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), + ), + Array.from( + Uint8Array.from(Buffer.from("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "hex")), + ), + ] + + const hashAccountsPDA = [] + for (const [index, adapterId] of ADAPTER_IDS.entries()) { + const [hashAccountPDA] = await PublicKey.findProgramAddressSync( + [Buffer.from("hash_account", "utf-8"), adapterId, DOMAIN, intToBytes32Buff(id)], + adapter.programId, + ) + + await adapter.methods + .storeHash(adapterId, DOMAIN, intToBytes32Buff(id), hashes[index]) + .accounts({ + hashAccount: hashAccountPDA, + user: provider.wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .rpc() + hashAccountsPDA.push(hashAccountPDA) + } + + await hashi.methods + .checkHashWithThresholdFromAdapters(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) + .remainingAccounts( + hashAccountsPDA.map((_hashAccountPDA) => ({ + isSigner: false, + isWritable: false, + pubkey: _hashAccountPDA, + })), + ) + .rpc() + }) + + it("should fail if the majority of adapters doesn't agree on an hash", async () => { + const threshold = 2 + const id = 1 + const hashes = [ + Array.from( + Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), + ), + Array.from( + Uint8Array.from(Buffer.from("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "hex")), + ), + Array.from( + Uint8Array.from(Buffer.from("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", "hex")), + ), + ] + + const hashAccountsPDA = [] + for (const [index, adapterId] of ADAPTER_IDS.entries()) { + const [hashAccountPDA] = await PublicKey.findProgramAddressSync( + [Buffer.from("hash_account", "utf-8"), adapterId, DOMAIN, intToBytes32Buff(id)], + adapter.programId, + ) + + await adapter.methods + .storeHash(adapterId, DOMAIN, intToBytes32Buff(id), hashes[index]) + .accounts({ + hashAccount: hashAccountPDA, + user: provider.wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .rpc() + hashAccountsPDA.push(hashAccountPDA) + } + + try { + await hashi.methods + .checkHashWithThresholdFromAdapters(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) + .remainingAccounts( + hashAccountsPDA.map((_hashAccountPDA) => ({ + isSigner: false, + isWritable: false, + pubkey: _hashAccountPDA, + })), + ) + .rpc() + } catch (_err) { + expect(_err.error.errorCode.code).to.be.eq("ThresholdNotMet") + } + }) +}) diff --git a/packages/solana/tests/utils.ts b/packages/solana/tests/utils.ts new file mode 100644 index 00000000..fdd6d70e --- /dev/null +++ b/packages/solana/tests/utils.ts @@ -0,0 +1 @@ +export const intToBytes32Buff = (_num: number) => Buffer.from(_num.toString(16).padStart(64, "0"), "hex") From 4abd108a1e991a0ca0e27fe211fed5e31b01cc33 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 27 Nov 2024 18:57:35 +0100 Subject: [PATCH 03/31] refactor(solana): organizes programs's folders better --- packages/solana/Cargo.lock | 1 + .../programs/adapter/src/contexts/mod.rs | 3 ++ .../adapter/src/contexts/store_hash.rs | 22 ++++++++++ packages/solana/programs/adapter/src/lib.rs | 39 +++-------------- .../adapter/src/state/hash_account.rs | 13 ++++++ .../solana/programs/adapter/src/state/mod.rs | 3 ++ packages/solana/programs/hashi/Cargo.toml | 1 + .../src/contexts/check_hash_with_threshold.rs | 4 ++ .../solana/programs/hashi/src/contexts/mod.rs | 3 ++ packages/solana/programs/hashi/src/error.rs | 19 ++++++++ packages/solana/programs/hashi/src/lib.rs | 43 +++++-------------- 11 files changed, 86 insertions(+), 65 deletions(-) create mode 100644 packages/solana/programs/adapter/src/contexts/mod.rs create mode 100644 packages/solana/programs/adapter/src/contexts/store_hash.rs create mode 100644 packages/solana/programs/adapter/src/state/hash_account.rs create mode 100644 packages/solana/programs/adapter/src/state/mod.rs create mode 100644 packages/solana/programs/hashi/src/contexts/check_hash_with_threshold.rs create mode 100644 packages/solana/programs/hashi/src/contexts/mod.rs create mode 100644 packages/solana/programs/hashi/src/error.rs diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index c50b5ff2..b06b8c95 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -851,6 +851,7 @@ checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" name = "hashi" version = "0.1.0" dependencies = [ + "adapter", "anchor-lang", ] diff --git a/packages/solana/programs/adapter/src/contexts/mod.rs b/packages/solana/programs/adapter/src/contexts/mod.rs new file mode 100644 index 00000000..2d59c226 --- /dev/null +++ b/packages/solana/programs/adapter/src/contexts/mod.rs @@ -0,0 +1,3 @@ +pub mod store_hash; + +pub use store_hash::*; diff --git a/packages/solana/programs/adapter/src/contexts/store_hash.rs b/packages/solana/programs/adapter/src/contexts/store_hash.rs new file mode 100644 index 00000000..0326edf3 --- /dev/null +++ b/packages/solana/programs/adapter/src/contexts/store_hash.rs @@ -0,0 +1,22 @@ +use crate::*; + +#[derive(Accounts)] +#[instruction(adapter_id: [u8; 32], domain: [u8; 32], id: [u8; 32])] +pub struct StoreHash<'info> { + #[account( + init_if_needed, + payer = user, + space = 8 + HashAccount::LEN, + seeds = [ + "hash_account".as_bytes(), + &adapter_id, + &domain, + &id + ], + bump, + )] + pub hash_account: Account<'info, HashAccount>, + #[account(mut)] + pub user: Signer<'info>, + pub system_program: Program<'info, System>, +} diff --git a/packages/solana/programs/adapter/src/lib.rs b/packages/solana/programs/adapter/src/lib.rs index a660bd9c..8ea41a88 100644 --- a/packages/solana/programs/adapter/src/lib.rs +++ b/packages/solana/programs/adapter/src/lib.rs @@ -2,6 +2,12 @@ use anchor_lang::prelude::*; declare_id!("E31NDsJknUaJ1VKGBCePkcZysajUqqFw5pDFAz1fFAGu"); +pub mod contexts; +pub mod state; + +pub use contexts::*; +pub use state::*; + #[program] pub mod adapter { use super::*; @@ -31,39 +37,6 @@ pub mod adapter { } } -#[account] -pub struct HashAccount { - pub adapter_id: [u8; 32], - pub domain: [u8; 32], - pub id: [u8; 32], - pub hash: [u8; 32], -} - -impl HashAccount { - pub const LEN: usize = 32 + 32 + 32 + 32; -} - -#[derive(Accounts)] -#[instruction(adapter_id: [u8; 32], domain: [u8; 32], id: [u8; 32])] -pub struct StoreHash<'info> { - #[account( - init_if_needed, - payer = user, - space = 8 + HashAccount::LEN, - seeds = [ - "hash_account".as_bytes(), - &adapter_id, - &domain, - &id - ], - bump, - )] - pub hash_account: Account<'info, HashAccount>, - #[account(mut)] - pub user: Signer<'info>, - pub system_program: Program<'info, System>, -} - #[event] pub struct HashStored { pub adapter_id: [u8; 32], diff --git a/packages/solana/programs/adapter/src/state/hash_account.rs b/packages/solana/programs/adapter/src/state/hash_account.rs new file mode 100644 index 00000000..fdd6e463 --- /dev/null +++ b/packages/solana/programs/adapter/src/state/hash_account.rs @@ -0,0 +1,13 @@ +use crate::*; + +#[account] +pub struct HashAccount { + pub adapter_id: [u8; 32], + pub domain: [u8; 32], + pub id: [u8; 32], + pub hash: [u8; 32], +} + +impl HashAccount { + pub const LEN: usize = 32 + 32 + 32 + 32; +} diff --git a/packages/solana/programs/adapter/src/state/mod.rs b/packages/solana/programs/adapter/src/state/mod.rs new file mode 100644 index 00000000..abfe3807 --- /dev/null +++ b/packages/solana/programs/adapter/src/state/mod.rs @@ -0,0 +1,3 @@ +pub mod hash_account; + +pub use hash_account::*; diff --git a/packages/solana/programs/hashi/Cargo.toml b/packages/solana/programs/hashi/Cargo.toml index 2f6aa167..8d17924e 100644 --- a/packages/solana/programs/hashi/Cargo.toml +++ b/packages/solana/programs/hashi/Cargo.toml @@ -18,3 +18,4 @@ idl-build = ["anchor-lang/idl-build"] [dependencies] anchor-lang = "0.30.1" +adapter = { path = "../adapter", features = ["cpi"] } \ No newline at end of file diff --git a/packages/solana/programs/hashi/src/contexts/check_hash_with_threshold.rs b/packages/solana/programs/hashi/src/contexts/check_hash_with_threshold.rs new file mode 100644 index 00000000..fe92a0f4 --- /dev/null +++ b/packages/solana/programs/hashi/src/contexts/check_hash_with_threshold.rs @@ -0,0 +1,4 @@ +use crate::*; + +#[derive(Accounts)] +pub struct CheckHashWithThreshold {} diff --git a/packages/solana/programs/hashi/src/contexts/mod.rs b/packages/solana/programs/hashi/src/contexts/mod.rs new file mode 100644 index 00000000..a0d4a2a9 --- /dev/null +++ b/packages/solana/programs/hashi/src/contexts/mod.rs @@ -0,0 +1,3 @@ +pub mod check_hash_with_threshold; + +pub use check_hash_with_threshold::*; diff --git a/packages/solana/programs/hashi/src/error.rs b/packages/solana/programs/hashi/src/error.rs new file mode 100644 index 00000000..8e8dbc35 --- /dev/null +++ b/packages/solana/programs/hashi/src/error.rs @@ -0,0 +1,19 @@ +use anchor_lang::prelude::*; + +#[error_code] +pub enum ErrorCode { + #[msg("The majority threshold was not met.")] + ThresholdNotMet, + #[msg("Invalid threshold: greater than the number of accounts provided.")] + InvalidThreshold, + #[msg("No accounts were provided.")] + NoAccountsProvided, + #[msg("Invalid adapter id.")] + InvalidAdapterId, + #[msg("Invalid adapter ids length.")] + InvalidAdapterIdsLength, + #[msg("Invalid domain.")] + InvalidId, + #[msg("Invalid id.")] + InvalidDomain, +} diff --git a/packages/solana/programs/hashi/src/lib.rs b/packages/solana/programs/hashi/src/lib.rs index d6967982..1b9d867d 100644 --- a/packages/solana/programs/hashi/src/lib.rs +++ b/packages/solana/programs/hashi/src/lib.rs @@ -1,14 +1,22 @@ use anchor_lang::prelude::*; use std::collections::HashMap; +use adapter::HashAccount; + declare_id!("EyqiZf8Yt2CgVU5yPsj5e4EiGXeKrLhefWBn7CSqKPMC"); +pub mod contexts; +pub mod error; + +pub use contexts::*; +pub use error::ErrorCode; + #[program] pub mod hashi { use super::*; - pub fn check_hash_with_threshold_from_adapters( - ctx: Context, + pub fn check_hash_with_threshold( + ctx: Context, adapter_ids: Vec<[u8; 32]>, domain: [u8; 32], id: [u8; 32], @@ -50,7 +58,7 @@ pub mod hashi { } let mut max_count = 0; - for (hash, count) in hash_counts.iter() { + for (_hash, count) in hash_counts.iter() { if *count > max_count { max_count = *count; } @@ -63,32 +71,3 @@ pub mod hashi { } } } - -#[derive(Accounts)] -pub struct ReadHashes {} - -#[account] -pub struct HashAccount { - pub adapter_id: [u8; 32], - pub domain: [u8; 32], - pub id: [u8; 32], - pub hash: [u8; 32], -} - -#[error_code] -pub enum ErrorCode { - #[msg("The majority threshold was not met.")] - ThresholdNotMet, - #[msg("Invalid threshold: greater than the number of accounts provided.")] - InvalidThreshold, - #[msg("No accounts were provided.")] - NoAccountsProvided, - #[msg("Invalid adapter id.")] - InvalidAdapterId, - #[msg("Invalid adapter ids length.")] - InvalidAdapterIdsLength, - #[msg("Invalid domain.")] - InvalidId, - #[msg("Invalid id.")] - InvalidDomain, -} From c22291764269175355f6ce1e95dfd743a67af66a Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 27 Nov 2024 18:58:01 +0100 Subject: [PATCH 04/31] feat(solana): adds hashi tests --- packages/solana/tests/hashi.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/solana/tests/hashi.ts b/packages/solana/tests/hashi.ts index 8dc428f4..97bc9146 100644 --- a/packages/solana/tests/hashi.ts +++ b/packages/solana/tests/hashi.ts @@ -55,7 +55,7 @@ describe("hashi", () => { } await hashi.methods - .checkHashWithThresholdFromAdapters(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) + .checkHashWithThreshold(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) .remainingAccounts( hashAccountsPDA.map((_hashAccountPDA) => ({ isSigner: false, @@ -101,7 +101,7 @@ describe("hashi", () => { try { await hashi.methods - .checkHashWithThresholdFromAdapters(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) + .checkHashWithThreshold(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) .remainingAccounts( hashAccountsPDA.map((_hashAccountPDA) => ({ isSigner: false, From 34593cacc7e4bf2df9249ea51605824d7200f090 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Fri, 29 Nov 2024 08:07:27 +0100 Subject: [PATCH 05/31] feat(solana): starts debridge_reporter --- packages/solana/Anchor.toml | 2 + packages/solana/Cargo.lock | 147 ++++++++++++++++++ .../programs/debridge-reporter/Cargo.toml | 21 +++ .../programs/debridge-reporter/Xargo.toml | 2 + .../src/contexts/dispatch_slot.rs | 9 ++ .../debridge-reporter/src/contexts/mod.rs | 3 + .../programs/debridge-reporter/src/error.rs | 13 ++ .../programs/debridge-reporter/src/lib.rs | 48 ++++++ .../programs/debridge-reporter/src/utils.rs | 46 ++++++ packages/solana/tests/debridge-reporter.ts | 126 +++++++++++++++ 10 files changed, 417 insertions(+) create mode 100644 packages/solana/programs/debridge-reporter/Cargo.toml create mode 100644 packages/solana/programs/debridge-reporter/Xargo.toml create mode 100644 packages/solana/programs/debridge-reporter/src/contexts/dispatch_slot.rs create mode 100644 packages/solana/programs/debridge-reporter/src/contexts/mod.rs create mode 100644 packages/solana/programs/debridge-reporter/src/error.rs create mode 100644 packages/solana/programs/debridge-reporter/src/lib.rs create mode 100644 packages/solana/programs/debridge-reporter/src/utils.rs create mode 100644 packages/solana/tests/debridge-reporter.ts diff --git a/packages/solana/Anchor.toml b/packages/solana/Anchor.toml index 6311454e..f5c43429 100644 --- a/packages/solana/Anchor.toml +++ b/packages/solana/Anchor.toml @@ -5,8 +5,10 @@ resolution = true skip-lint = false [programs.localnet] +debridge-reporter = "2TvQ6gqQGAifdV2cQ1f8zHGYV2t6wPUNTKzpcALt8rX7" hashi = "EyqiZf8Yt2CgVU5yPsj5e4EiGXeKrLhefWBn7CSqKPMC" help = "EJy8wh5fqP5LYqs1mNbH2S6jxKGkP64PkXRmZgQxk9CE" +reporter = "4wFzP8uwPvvW2kZGxxkL45SP2Wn3oRbfe1LdHheUFZ9k" solana = "4VFxPo4BF53PkVFBFjCQBFUn8bCxZZm6Dc2VgrJ5HXS8" [registry] diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index b06b8c95..9de09468 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -369,6 +369,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -631,6 +637,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg-match" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8100e46ff92eb85bf6dc2930c73f2a4f7176393c84a9446b3d501e1b354e7b34" + [[package]] name = "cfg_aliases" version = "0.2.1" @@ -737,6 +749,66 @@ dependencies = [ "zeroize", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "debridge-reporter" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "debridge-solana-sdk", +] + +[[package]] +name = "debridge-solana-sdk" +version = "1.0.2" +source = "git+ssh://git@github.com/debridge-finance/debridge-solana-sdk.git#e442dd77f2cab1082a7140be3602314567e4b4b6" +dependencies = [ + "borsh 0.9.3", + "cfg-match", + "derive_builder", + "env_to_array", + "hex", + "lazy_static", + "sha3", + "solana-program", + "some-to-err", + "thiserror", +] + [[package]] name = "derivative" version = "2.2.0" @@ -748,6 +820,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + [[package]] name = "digest" version = "0.9.0" @@ -774,6 +877,20 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "env_to_array" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "820a716148b32af5a6bc12fd0f06463ba3b461e8e9b40e3000a0b928dceb4f94" +dependencies = [ + "base64 0.13.1", + "bs58 0.4.0", + "hex", + "itertools", + "proc-macro2", + "syn 1.0.109", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -786,6 +903,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "generic-array" version = "0.14.7" @@ -864,6 +987,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hmac" version = "0.8.1" @@ -885,6 +1014,12 @@ dependencies = [ "hmac", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "im" version = "15.1.0" @@ -1587,6 +1722,18 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "some-to-err" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d95fd601e937c6e1fe0f25ef8754008e7bf87e97a8a60a8a60b0a289f7e39ad" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "2.6.1" diff --git a/packages/solana/programs/debridge-reporter/Cargo.toml b/packages/solana/programs/debridge-reporter/Cargo.toml new file mode 100644 index 00000000..04a2d091 --- /dev/null +++ b/packages/solana/programs/debridge-reporter/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "debridge-reporter" +version = "0.1.0" +description = "Debridge reporter" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] +name = "debridge_reporter" + +[features] +default = [] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build"] + +[dependencies] +anchor-lang = "0.30.1" +debridge-solana-sdk = { git = "ssh://git@github.com/debridge-finance/debridge-solana-sdk.git", version = "1.0.2" } diff --git a/packages/solana/programs/debridge-reporter/Xargo.toml b/packages/solana/programs/debridge-reporter/Xargo.toml new file mode 100644 index 00000000..475fb71e --- /dev/null +++ b/packages/solana/programs/debridge-reporter/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/packages/solana/programs/debridge-reporter/src/contexts/dispatch_slot.rs b/packages/solana/programs/debridge-reporter/src/contexts/dispatch_slot.rs new file mode 100644 index 00000000..0fbefcab --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/contexts/dispatch_slot.rs @@ -0,0 +1,9 @@ +use anchor_lang::prelude::*; +use anchor_lang::solana_program::sysvar; + +#[derive(Accounts)] +pub struct DispatchSlot<'info> { + /// CHECK: We are reading from SlotHashes sysvar the latest slot hash + #[account(address = sysvar::slot_hashes::ID)] + pub slot_hashes: AccountInfo<'info>, +} diff --git a/packages/solana/programs/debridge-reporter/src/contexts/mod.rs b/packages/solana/programs/debridge-reporter/src/contexts/mod.rs new file mode 100644 index 00000000..ce3e13db --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/contexts/mod.rs @@ -0,0 +1,3 @@ +pub mod dispatch_slot; + +pub use dispatch_slot::*; diff --git a/packages/solana/programs/debridge-reporter/src/error.rs b/packages/solana/programs/debridge-reporter/src/error.rs new file mode 100644 index 00000000..c0863a9d --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/error.rs @@ -0,0 +1,13 @@ +use anchor_lang::prelude::*; + +#[error_code] +pub enum ErrorCode { + #[msg("Invalid latest hash hash.")] + InvalidLatestHashLength, + #[msg("Invalid slot hashes sysvar.")] + InvalidSlotHashesSysVar, + #[msg("Slot hashes not available.")] + SlotHashesNotAvailable, + #[msg("Slot not found")] + SlotNotFound, +} diff --git a/packages/solana/programs/debridge-reporter/src/lib.rs b/packages/solana/programs/debridge-reporter/src/lib.rs new file mode 100644 index 00000000..a1ff0262 --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/lib.rs @@ -0,0 +1,48 @@ +use anchor_lang::prelude::*; +use borsh::{BorshDeserialize, BorshSerialize}; +use debridge_solana_sdk::sending; + +declare_id!("2TvQ6gqQGAifdV2cQ1f8zHGYV2t6wPUNTKzpcALt8rX7"); + +pub mod contexts; +pub mod error; +pub mod utils; + +pub use contexts::*; +pub use utils::{get_slot, u64_to_u8_32}; + +#[derive(BorshSerialize)] +pub struct Message { + pub ids: Vec<[u8; 32]>, + pub hashes: Vec<[u8; 32]>, +} + +#[program] +pub mod debridge_reporter { + use super::*; + + pub fn dispatch_slot( + ctx: Context, + target_chain_id: [u8; 32], + receiver: Vec, + slot_number: u64, + ) -> Result<()> { + let (number, hash) = get_slot(&ctx.accounts.slot_hashes, slot_number)?; + + let ids: Vec<[u8; 32]> = vec![u64_to_u8_32(number)]; + let hashes: Vec<[u8; 32]> = vec![hash]; + let message = Message { ids, hashes }; + + sending::invoke_send_message( + message.try_to_vec()?, + target_chain_id, + receiver, + 0, // execution_fee = 0 means auto claim + vec![0u8; 32], // fallback address + ctx.remaining_accounts, + ) + .map_err(ProgramError::from)?; + + Ok(()) + } +} diff --git a/packages/solana/programs/debridge-reporter/src/utils.rs b/packages/solana/programs/debridge-reporter/src/utils.rs new file mode 100644 index 00000000..89bb4c27 --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/utils.rs @@ -0,0 +1,46 @@ +use anchor_lang::prelude::*; +use anchor_lang::solana_program::sysvar; + +use crate::error::ErrorCode; + +pub fn get_slot(slot_hashes: &AccountInfo, slot_number: u64) -> Result<(u64, [u8; 32])> { + if *slot_hashes.key != sysvar::slot_hashes::ID { + return Err(error!(ErrorCode::InvalidSlotHashesSysVar)); + } + + let data = slot_hashes.try_borrow_data()?; + let num_slot_hashes = u64::from_le_bytes(data[0..8].try_into().unwrap()); + let mut pos = 8; + + if num_slot_hashes == 0 { + return Err(error!(ErrorCode::SlotHashesNotAvailable)); + } + + for _i in 0..num_slot_hashes { + let current_slot_number = u64::from_le_bytes(data[pos..pos + 8].try_into().unwrap()); + pos += 8; + + let current_slot_hash: [u8; 32] = match &data[pos..pos + 32].try_into() { + Ok(hash) => *hash, + Err(_) => return Err(error!(ErrorCode::InvalidLatestHashLength)), + }; + + if current_slot_number == slot_number { + return Ok((current_slot_number, current_slot_hash)); + } + + pos += 32; + } + + Err(error!(ErrorCode::SlotNotFound)) +} + +pub fn u64_to_u8_32(number: u64) -> [u8; 32] { + let mut bytes = [0u8; 32]; + let number_bytes = number.to_be_bytes(); // Convert u64 to a big-endian 8-byte array + + // Copy the 8 bytes of the u64 into the last 8 bytes of the 32-byte array + bytes[24..].copy_from_slice(&number_bytes); + + bytes +} diff --git a/packages/solana/tests/debridge-reporter.ts b/packages/solana/tests/debridge-reporter.ts new file mode 100644 index 00000000..6027c141 --- /dev/null +++ b/packages/solana/tests/debridge-reporter.ts @@ -0,0 +1,126 @@ +/*import * as anchor from "@coral-xyz/anchor" +import { Program } from "@coral-xyz/anchor" +import { AccountMeta, PublicKey, SYSVAR_SLOT_HASHES_PUBKEY } from "@solana/web3.js" +// import { expect } from "chai" + +import { DebridgeReporter } from "../target/types/debridge_reporter" + +const accountsToMeta = () => { + const result: AccountMeta[] = [ + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("6SW1N9Rq2TqT3uQCD4F5zwtTTSFSarZmfyrk829SzsBX"), + }, + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("So11111111111111111111111111111111111111112"), + }, + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("8gjgVkHXTttCoSGGtzucFkJUWujQ8pgWuvnHCLSN7i3o"), + }, + { + isSigner: false, + isWritable: false, + pubkey: new PublicKey("7FmGdfJfDrrM6P68y7jijjj4xU9rH3hsUK2Kyp54iJUx"), + }, + { + isSigner: false, + isWritable: false, + pubkey: new PublicKey("8L81QZBfwA6Xi9zd49fyUfMRWJBCAxiUxd6jGHPnu1BQ"), + }, + { + isSigner: false, + isWritable: false, + pubkey: new PublicKey("DeSetTwWhjZq6Pz9Kfdo1KoS5NqtsM6G8ERbX4SSCSft"), + }, + { + isSigner: false, + isWritable: false, + pubkey: new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"), + }, + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("CcjkxrCJvfXrmds78hwCnovkdmTgE12wqojiVLrtW1qn"), + }, + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("5MgAaNomDg4Y88v7gJ7LSWAyoLpDfcfbXZGQQnFddjJT"), + }, + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("2LKQceMRwfJNZovtSbsHmfszDYM5kTZHajFry2nqD2pi"), + }, + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("BzoSTqbp8vZ54Baq2K4LTwGnC8fYvKiEFQDNxdEDnosG"), + }, + { + isSigner: false, + isWritable: false, + pubkey: new PublicKey("11111111111111111111111111111111"), + }, + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("dPLMV1ky3H61yRGFfNC6AYmzBePhsdes9oNZ7chPbYW"), + }, + { + isSigner: false, + isWritable: true, + pubkey: new PublicKey("2cU8vjsMnRcusX1WdwZy1AwCLrUWbDw6frnk3XDz3VVK"), + }, + { + isSigner: true, + isWritable: true, + pubkey: new PublicKey("FsiBNh2KcPrjZFMF7EBCWpUpAo95DfrMXB2U2XrqSFWF"), + }, + { + isSigner: false, + isWritable: false, + pubkey: new PublicKey("4kQYWVy6Vu8YUXVp5BgQC12ZX1HLRUfkK3bLzBFFjnNW"), + }, + { + isSigner: false, + isWritable: false, + pubkey: new PublicKey("APMGxdbtubfWLQUACsN2yv2pxkvAgWwuxBe8ohFYoB37"), + }, + { + isSigner: false, + isWritable: false, + pubkey: new PublicKey("DEbrdGj3HsRsAzx6uH4MKyREKxVAfBydijLUF3ygsFfh"), + }, + ] + + return result +} + +describe("debridge_reporter", () => { + const provider = anchor.AnchorProvider.local() + anchor.setProvider(provider) + + const reporter = anchor.workspace.DebridgeReporter as Program + + it("should dispatch a slot", async () => { + const targetChainId = Buffer.from("1".padStart(64, "0"), "hex") + const receiver = Buffer.from("1".padStart(40, "1"), "hex") + const slot = await provider.connection.getSlot() + const slotNumberToDispatch = new anchor.BN(slot - 1) + + await reporter.methods + .dispatchSlot(targetChainId, receiver, slotNumberToDispatch) + .accounts({ + slotHashes: SYSVAR_SLOT_HASHES_PUBKEY, + }) + .remainingAccounts([...accountsToMeta()]) + .rpc() + }) +}) +*/ From bfc7770095bee2dd48c8c2218d86720425764b6b Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Fri, 29 Nov 2024 14:39:39 +0100 Subject: [PATCH 06/31] feat(solana): adds shared folder --- packages/solana/Cargo.toml | 3 ++- .../programs/debridge-reporter/Cargo.toml | 3 ++- .../programs/debridge-reporter/src/error.rs | 13 ------------ .../programs/debridge-reporter/src/lib.rs | 11 +++++++--- packages/solana/shared/slots/Cargo.toml | 16 +++++++++++++++ .../src/utils.rs => shared/slots/src/lib.rs} | 20 +++++++++---------- 6 files changed, 38 insertions(+), 28 deletions(-) delete mode 100644 packages/solana/programs/debridge-reporter/src/error.rs create mode 100644 packages/solana/shared/slots/Cargo.toml rename packages/solana/{programs/debridge-reporter/src/utils.rs => shared/slots/src/lib.rs} (76%) diff --git a/packages/solana/Cargo.toml b/packages/solana/Cargo.toml index f3977048..e151e9d4 100644 --- a/packages/solana/Cargo.toml +++ b/packages/solana/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ - "programs/*" + "programs/*", + "shared/*" ] resolver = "2" diff --git a/packages/solana/programs/debridge-reporter/Cargo.toml b/packages/solana/programs/debridge-reporter/Cargo.toml index 04a2d091..cd0a8ea3 100644 --- a/packages/solana/programs/debridge-reporter/Cargo.toml +++ b/packages/solana/programs/debridge-reporter/Cargo.toml @@ -18,4 +18,5 @@ idl-build = ["anchor-lang/idl-build"] [dependencies] anchor-lang = "0.30.1" -debridge-solana-sdk = { git = "ssh://git@github.com/debridge-finance/debridge-solana-sdk.git", version = "1.0.2" } +debridge-solana-sdk = "1.0.1" +slots = { path = "../../shared/slots" } \ No newline at end of file diff --git a/packages/solana/programs/debridge-reporter/src/error.rs b/packages/solana/programs/debridge-reporter/src/error.rs deleted file mode 100644 index c0863a9d..00000000 --- a/packages/solana/programs/debridge-reporter/src/error.rs +++ /dev/null @@ -1,13 +0,0 @@ -use anchor_lang::prelude::*; - -#[error_code] -pub enum ErrorCode { - #[msg("Invalid latest hash hash.")] - InvalidLatestHashLength, - #[msg("Invalid slot hashes sysvar.")] - InvalidSlotHashesSysVar, - #[msg("Slot hashes not available.")] - SlotHashesNotAvailable, - #[msg("Slot not found")] - SlotNotFound, -} diff --git a/packages/solana/programs/debridge-reporter/src/lib.rs b/packages/solana/programs/debridge-reporter/src/lib.rs index a1ff0262..0c55b98b 100644 --- a/packages/solana/programs/debridge-reporter/src/lib.rs +++ b/packages/solana/programs/debridge-reporter/src/lib.rs @@ -1,15 +1,13 @@ use anchor_lang::prelude::*; use borsh::{BorshDeserialize, BorshSerialize}; use debridge_solana_sdk::sending; +use slots::get_slot; declare_id!("2TvQ6gqQGAifdV2cQ1f8zHGYV2t6wPUNTKzpcALt8rX7"); pub mod contexts; -pub mod error; -pub mod utils; pub use contexts::*; -pub use utils::{get_slot, u64_to_u8_32}; #[derive(BorshSerialize)] pub struct Message { @@ -46,3 +44,10 @@ pub mod debridge_reporter { Ok(()) } } + +pub fn u64_to_u8_32(number: u64) -> [u8; 32] { + let mut bytes = [0u8; 32]; + let number_bytes = number.to_be_bytes(); + bytes[24..].copy_from_slice(&number_bytes); + bytes +} diff --git a/packages/solana/shared/slots/Cargo.toml b/packages/solana/shared/slots/Cargo.toml new file mode 100644 index 00000000..a62818ab --- /dev/null +++ b/packages/solana/shared/slots/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "slots" +version = "0.1.0" +description = "Utilities functions to access Solana slots" +edition = "2021" + +[features] +default = [] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build"] + +[dependencies] +anchor-lang = "0.30.1" \ No newline at end of file diff --git a/packages/solana/programs/debridge-reporter/src/utils.rs b/packages/solana/shared/slots/src/lib.rs similarity index 76% rename from packages/solana/programs/debridge-reporter/src/utils.rs rename to packages/solana/shared/slots/src/lib.rs index 89bb4c27..5ddb70d4 100644 --- a/packages/solana/programs/debridge-reporter/src/utils.rs +++ b/packages/solana/shared/slots/src/lib.rs @@ -1,8 +1,6 @@ use anchor_lang::prelude::*; use anchor_lang::solana_program::sysvar; -use crate::error::ErrorCode; - pub fn get_slot(slot_hashes: &AccountInfo, slot_number: u64) -> Result<(u64, [u8; 32])> { if *slot_hashes.key != sysvar::slot_hashes::ID { return Err(error!(ErrorCode::InvalidSlotHashesSysVar)); @@ -35,12 +33,14 @@ pub fn get_slot(slot_hashes: &AccountInfo, slot_number: u64) -> Result<(u64, [u8 Err(error!(ErrorCode::SlotNotFound)) } -pub fn u64_to_u8_32(number: u64) -> [u8; 32] { - let mut bytes = [0u8; 32]; - let number_bytes = number.to_be_bytes(); // Convert u64 to a big-endian 8-byte array - - // Copy the 8 bytes of the u64 into the last 8 bytes of the 32-byte array - bytes[24..].copy_from_slice(&number_bytes); - - bytes +#[error_code] +pub enum ErrorCode { + #[msg("Invalid latest hash hash.")] + InvalidLatestHashLength, + #[msg("Invalid slot hashes sysvar.")] + InvalidSlotHashesSysVar, + #[msg("Slot hashes not available.")] + SlotHashesNotAvailable, + #[msg("Slot not found")] + SlotNotFound, } From 7ce941bca53b2a796c9b8061075acca285121e14 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Fri, 29 Nov 2024 16:31:12 +0100 Subject: [PATCH 07/31] feat(solana): adds Message --- .../programs/debridge-reporter/Cargo.toml | 3 +- .../programs/debridge-reporter/src/lib.rs | 28 ++++--------------- packages/solana/shared/message/Cargo.toml | 16 +++++++++++ packages/solana/shared/message/src/lib.rs | 26 +++++++++++++++++ packages/solana/shared/slots/src/lib.rs | 4 +-- 5 files changed, 51 insertions(+), 26 deletions(-) create mode 100644 packages/solana/shared/message/Cargo.toml create mode 100644 packages/solana/shared/message/src/lib.rs diff --git a/packages/solana/programs/debridge-reporter/Cargo.toml b/packages/solana/programs/debridge-reporter/Cargo.toml index cd0a8ea3..1474468b 100644 --- a/packages/solana/programs/debridge-reporter/Cargo.toml +++ b/packages/solana/programs/debridge-reporter/Cargo.toml @@ -19,4 +19,5 @@ idl-build = ["anchor-lang/idl-build"] [dependencies] anchor-lang = "0.30.1" debridge-solana-sdk = "1.0.1" -slots = { path = "../../shared/slots" } \ No newline at end of file +slots = { path = "../../shared/slots" } +message = { path = "../../shared/message" } \ No newline at end of file diff --git a/packages/solana/programs/debridge-reporter/src/lib.rs b/packages/solana/programs/debridge-reporter/src/lib.rs index 0c55b98b..7136837f 100644 --- a/packages/solana/programs/debridge-reporter/src/lib.rs +++ b/packages/solana/programs/debridge-reporter/src/lib.rs @@ -1,7 +1,4 @@ use anchor_lang::prelude::*; -use borsh::{BorshDeserialize, BorshSerialize}; -use debridge_solana_sdk::sending; -use slots::get_slot; declare_id!("2TvQ6gqQGAifdV2cQ1f8zHGYV2t6wPUNTKzpcALt8rX7"); @@ -9,15 +6,12 @@ pub mod contexts; pub use contexts::*; -#[derive(BorshSerialize)] -pub struct Message { - pub ids: Vec<[u8; 32]>, - pub hashes: Vec<[u8; 32]>, -} - #[program] pub mod debridge_reporter { use super::*; + use debridge_solana_sdk::sending; + use message::Message; + use slots::get_slot; pub fn dispatch_slot( ctx: Context, @@ -25,12 +19,8 @@ pub mod debridge_reporter { receiver: Vec, slot_number: u64, ) -> Result<()> { - let (number, hash) = get_slot(&ctx.accounts.slot_hashes, slot_number)?; - - let ids: Vec<[u8; 32]> = vec![u64_to_u8_32(number)]; - let hashes: Vec<[u8; 32]> = vec![hash]; - let message = Message { ids, hashes }; - + let slot_hash = get_slot(&ctx.accounts.slot_hashes, slot_number)?; + let message = Message::from((slot_number, slot_hash)); sending::invoke_send_message( message.try_to_vec()?, target_chain_id, @@ -40,14 +30,6 @@ pub mod debridge_reporter { ctx.remaining_accounts, ) .map_err(ProgramError::from)?; - Ok(()) } } - -pub fn u64_to_u8_32(number: u64) -> [u8; 32] { - let mut bytes = [0u8; 32]; - let number_bytes = number.to_be_bytes(); - bytes[24..].copy_from_slice(&number_bytes); - bytes -} diff --git a/packages/solana/shared/message/Cargo.toml b/packages/solana/shared/message/Cargo.toml new file mode 100644 index 00000000..90775306 --- /dev/null +++ b/packages/solana/shared/message/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "message" +version = "0.1.0" +description = "Message struct to use within Hashi" +edition = "2021" + +[features] +default = [] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build"] + +[dependencies] +anchor-lang = "0.30.1" \ No newline at end of file diff --git a/packages/solana/shared/message/src/lib.rs b/packages/solana/shared/message/src/lib.rs new file mode 100644 index 00000000..9344d428 --- /dev/null +++ b/packages/solana/shared/message/src/lib.rs @@ -0,0 +1,26 @@ +use anchor_lang::prelude::*; +use borsh::{BorshDeserialize, BorshSerialize}; +use std::convert::From; + +#[derive(BorshDeserialize, BorshSerialize)] +pub struct Message { + pub ids: Vec<[u8; 32]>, + pub hashes: Vec<[u8; 32]>, +} + +impl From<(u64, [u8; 32])> for Message { + fn from(value: (u64, [u8; 32])) -> Self { + let (id, hash) = value; + Message { + ids: vec![u64_to_u8_32(id)], + hashes: vec![hash], + } + } +} + +fn u64_to_u8_32(number: u64) -> [u8; 32] { + let mut bytes = [0u8; 32]; + let number_bytes = number.to_be_bytes(); + bytes[24..].copy_from_slice(&number_bytes); + bytes +} diff --git a/packages/solana/shared/slots/src/lib.rs b/packages/solana/shared/slots/src/lib.rs index 5ddb70d4..53f0aa51 100644 --- a/packages/solana/shared/slots/src/lib.rs +++ b/packages/solana/shared/slots/src/lib.rs @@ -1,7 +1,7 @@ use anchor_lang::prelude::*; use anchor_lang::solana_program::sysvar; -pub fn get_slot(slot_hashes: &AccountInfo, slot_number: u64) -> Result<(u64, [u8; 32])> { +pub fn get_slot(slot_hashes: &AccountInfo, slot_number: u64) -> Result<[u8; 32]> { if *slot_hashes.key != sysvar::slot_hashes::ID { return Err(error!(ErrorCode::InvalidSlotHashesSysVar)); } @@ -24,7 +24,7 @@ pub fn get_slot(slot_hashes: &AccountInfo, slot_number: u64) -> Result<(u64, [u8 }; if current_slot_number == slot_number { - return Ok((current_slot_number, current_slot_hash)); + return Ok(current_slot_hash); } pos += 32; From 3b323c722caeacfcf704f2d5cfeac77ab84995f6 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Fri, 29 Nov 2024 17:14:41 +0100 Subject: [PATCH 08/31] feat(solana): adds a first version of wormhole-reporter --- packages/solana/Anchor.toml | 1 + packages/solana/Cargo.lock | 828 +++++++++++++++++- .../programs/wormhole-reporter/Cargo.toml | 27 + .../programs/wormhole-reporter/Xargo.toml | 2 + .../src/contexts/dispatch_slot.rs | 85 ++ .../src/contexts/initialize.rs | 103 +++ .../wormhole-reporter/src/contexts/mod.rs | 5 + .../programs/wormhole-reporter/src/error.rs | 41 + .../programs/wormhole-reporter/src/lib.rs | 150 ++++ .../programs/wormhole-reporter/src/message.rs | 206 +++++ .../wormhole-reporter/src/state/config.rs | 48 + .../wormhole-reporter/src/state/mod.rs | 5 + .../src/state/wormhole_emitter.rs | 35 + 13 files changed, 1516 insertions(+), 20 deletions(-) create mode 100644 packages/solana/programs/wormhole-reporter/Cargo.toml create mode 100644 packages/solana/programs/wormhole-reporter/Xargo.toml create mode 100644 packages/solana/programs/wormhole-reporter/src/contexts/dispatch_slot.rs create mode 100644 packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs create mode 100644 packages/solana/programs/wormhole-reporter/src/contexts/mod.rs create mode 100644 packages/solana/programs/wormhole-reporter/src/error.rs create mode 100644 packages/solana/programs/wormhole-reporter/src/lib.rs create mode 100644 packages/solana/programs/wormhole-reporter/src/message.rs create mode 100644 packages/solana/programs/wormhole-reporter/src/state/config.rs create mode 100644 packages/solana/programs/wormhole-reporter/src/state/mod.rs create mode 100644 packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs diff --git a/packages/solana/Anchor.toml b/packages/solana/Anchor.toml index f5c43429..325f23c8 100644 --- a/packages/solana/Anchor.toml +++ b/packages/solana/Anchor.toml @@ -10,6 +10,7 @@ hashi = "EyqiZf8Yt2CgVU5yPsj5e4EiGXeKrLhefWBn7CSqKPMC" help = "EJy8wh5fqP5LYqs1mNbH2S6jxKGkP64PkXRmZgQxk9CE" reporter = "4wFzP8uwPvvW2kZGxxkL45SP2Wn3oRbfe1LdHheUFZ9k" solana = "4VFxPo4BF53PkVFBFjCQBFUn8bCxZZm6Dc2VgrJ5HXS8" +wormhole-reporter = "4y9MQDaWZrfghUAJPmm9uJwCEyZzNZSzPVxs1WKbMXbn" [registry] url = "https://api.apr.dev" diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index 9de09468..7e3de302 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -9,6 +9,42 @@ dependencies = [ "anchor-lang", ] +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + [[package]] name = "ahash" version = "0.7.8" @@ -203,6 +239,22 @@ dependencies = [ "serde", ] +[[package]] +name = "anchor-spl" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04bd077c34449319a1e4e0bc21cea572960c9ae0d0fefda0dd7c52fcc3c647a3" +dependencies = [ + "anchor-lang", + "mpl-token-metadata", + "spl-associated-token-account", + "spl-pod", + "spl-token", + "spl-token-2022", + "spl-token-group-interface", + "spl-token-metadata-interface", +] + [[package]] name = "anchor-syn" version = "0.30.1" @@ -357,6 +409,23 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -428,6 +497,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ + "block-padding", "generic-array", ] @@ -440,6 +510,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + [[package]] name = "borsh" version = "0.9.3" @@ -649,6 +725,24 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "num-traits", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -735,6 +829,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "3.2.1" @@ -755,8 +858,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -769,33 +882,61 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.89", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core 0.20.10", + "quote", + "syn 2.0.89", +] + [[package]] name = "debridge-reporter" version = "0.1.0" dependencies = [ "anchor-lang", "debridge-solana-sdk", + "message", + "slots", ] [[package]] name = "debridge-solana-sdk" -version = "1.0.2" -source = "git+ssh://git@github.com/debridge-finance/debridge-solana-sdk.git#e442dd77f2cab1082a7140be3602314567e4b4b6" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac97e77dab5301c48a882cb08277733006aadbf52a7409e8ca69e8da9446d88" dependencies = [ "borsh 0.9.3", "cfg-match", @@ -803,12 +944,17 @@ dependencies = [ "env_to_array", "hex", "lazy_static", - "sha3", + "sha3 0.10.8", "solana-program", - "some-to-err", "thiserror", ] +[[package]] +name = "derivation-path" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" + [[package]] name = "derivative" version = "2.2.0" @@ -835,7 +981,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", @@ -871,12 +1017,60 @@ dependencies = [ "subtle", ] +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "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", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek-bip32" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" +dependencies = [ + "derivation-path", + "ed25519-dalek", + "hmac 0.12.1", + "sha2 0.10.8", +] + [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "env_to_array" version = "0.1.2" @@ -987,6 +1181,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -1003,6 +1206,15 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "hmac-drbg" version = "0.3.0" @@ -1011,9 +1223,15 @@ checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", "generic-array", - "hmac", + "hmac 0.8.1", ] +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "ident_case" version = "1.0.1" @@ -1200,6 +1418,38 @@ dependencies = [ "autocfg", ] +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "message" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + +[[package]] +name = "mpl-token-metadata" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf0f61b553e424a6234af1268456972ee66c2222e1da89079242251fa7479e5" +dependencies = [ + "borsh 0.10.4", + "num-derive 0.3.3", + "num-traits", + "solana-program", + "thiserror", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -1210,6 +1460,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "num-derive" version = "0.4.2" @@ -1239,6 +1500,27 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "once_cell" version = "1.20.2" @@ -1289,6 +1571,33 @@ dependencies = [ "crypto-mac", ] +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -1325,6 +1634,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "qstring" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "qualifier_attr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "quote" version = "1.0.37" @@ -1561,6 +1890,28 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +dependencies = [ + "darling 0.20.10", + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "sha2" version = "0.9.9" @@ -1585,6 +1936,18 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug", +] + [[package]] name = "sha3" version = "0.10.8" @@ -1601,6 +1964,18 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "sized-chunks" version = "0.6.5" @@ -1612,7 +1987,14 @@ dependencies = [ ] [[package]] -name = "smallvec" +name = "slots" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + +[[package]] +name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" @@ -1654,6 +2036,17 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "solana-logger" +version = "1.18.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121d36ffb3c6b958763312cbc697fbccba46ee837d3a0aa4fc0e90fcb3b884f3" +dependencies = [ + "env_logger", + "lazy_static", + "log", +] + [[package]] name = "solana-program" version = "1.18.26" @@ -1688,7 +2081,7 @@ dependencies = [ "log", "memoffset", "num-bigint", - "num-derive", + "num-derive 0.4.2", "num-traits", "parking_lot", "rand 0.8.5", @@ -1699,7 +2092,7 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.10.8", - "sha3", + "sha3 0.10.8", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-sdk-macro", @@ -1709,6 +2102,61 @@ dependencies = [ "zeroize", ] +[[package]] +name = "solana-sdk" +version = "1.18.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "580ad66c2f7a4c3cb3244fe21440546bd500f5ecb955ad9826e92a78dded8009" +dependencies = [ + "assert_matches", + "base64 0.21.7", + "bincode", + "bitflags", + "borsh 1.5.3", + "bs58 0.4.0", + "bytemuck", + "byteorder", + "chrono", + "derivation-path", + "digest 0.10.7", + "ed25519-dalek", + "ed25519-dalek-bip32", + "generic-array", + "hmac 0.12.1", + "itertools", + "js-sys", + "lazy_static", + "libsecp256k1", + "log", + "memmap2", + "num-derive 0.4.2", + "num-traits", + "num_enum", + "pbkdf2 0.11.0", + "qstring", + "qualifier_attr", + "rand 0.7.3", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "serde_with", + "sha2 0.10.8", + "sha3 0.10.8", + "siphasher", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-logger", + "solana-program", + "solana-sdk-macro", + "thiserror", + "uriparse", + "wasm-bindgen", +] + [[package]] name = "solana-sdk-macro" version = "1.18.26" @@ -1723,10 +2171,246 @@ dependencies = [ ] [[package]] -name = "some-to-err" -version = "0.2.1" +name = "solana-security-txt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183" + +[[package]] +name = "solana-zk-token-sdk" +version = "1.18.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cbdf4249b6dfcbba7d84e2b53313698043f60f8e22ce48286e6fbe8a17c8d16" +dependencies = [ + "aes-gcm-siv", + "base64 0.21.7", + "bincode", + "bytemuck", + "byteorder", + "curve25519-dalek", + "getrandom 0.1.16", + "itertools", + "lazy_static", + "merlin", + "num-derive 0.4.2", + "num-traits", + "rand 0.7.3", + "serde", + "serde_json", + "sha3 0.9.1", + "solana-program", + "solana-sdk", + "subtle", + "thiserror", + "zeroize", +] + +[[package]] +name = "spl-associated-token-account" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143109d789171379e6143ef23191786dfaac54289ad6e7917cfb26b36c432b10" +dependencies = [ + "assert_matches", + "borsh 1.5.3", + "num-derive 0.4.2", + "num-traits", + "solana-program", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "spl-discriminator" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "210101376962bb22bb13be6daea34656ea1cbc248fce2164b146e39203b55e03" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator-derive", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" +dependencies = [ + "quote", + "spl-discriminator-syn", + "syn 2.0.89", +] + +[[package]] +name = "spl-discriminator-syn" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.89", + "thiserror", +] + +[[package]] +name = "spl-memo" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a49f49f95f2d02111ded31696ab38a081fab623d4c76bd4cb074286db4560836" +dependencies = [ + "solana-program", +] + +[[package]] +name = "spl-pod" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c52d84c55efeef8edcc226743dc089d7e3888b8e3474569aa3eff152b37b9996" +dependencies = [ + "borsh 1.5.3", + "bytemuck", + "solana-program", + "solana-zk-token-sdk", + "spl-program-error", +] + +[[package]] +name = "spl-program-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e45a49acb925db68aa501b926096b2164adbdcade7a0c24152af9f0742d0a602" +dependencies = [ + "num-derive 0.4.2", + "num-traits", + "solana-program", + "spl-program-error-derive", + "thiserror", +] + +[[package]] +name = "spl-program-error-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.89", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fab8edfd37be5fa17c9e42c1bff86abbbaf0494b031b37957f2728ad2ff842ba" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + +[[package]] +name = "spl-token" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d95fd601e937c6e1fe0f25ef8754008e7bf87e97a8a60a8a60b0a289f7e39ad" +checksum = "b9eb465e4bf5ce1d498f05204c8089378c1ba34ef2777ea95852fc53a1fd4fb2" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.4.2", + "num-traits", + "num_enum", + "solana-program", + "thiserror", +] + +[[package]] +name = "spl-token-2022" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d1b2851964e257187c0bca43a0de38d0af59192479ca01ac3e2b58b1bd95a" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.4.2", + "num-traits", + "num_enum", + "solana-program", + "solana-security-txt", + "solana-zk-token-sdk", + "spl-memo", + "spl-pod", + "spl-token", + "spl-token-group-interface", + "spl-token-metadata-interface", + "spl-transfer-hook-interface", + "spl-type-length-value", + "thiserror", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "014817d6324b1e20c4bbc883e8ee30a5faa13e59d91d1b2b95df98b920150c17" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3da00495b602ebcf5d8ba8b3ecff1ee454ce4c125c9077747be49c2d62335ba" +dependencies = [ + "borsh 1.5.3", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b5c08a89838e5a2931f79b17f611857f281a14a2100968a3ccef352cb7414b" +dependencies = [ + "arrayref", + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-tlv-account-resolution", + "spl-type-length-value", +] + +[[package]] +name = "spl-type-length-value" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c872f93d0600e743116501eba2d53460e73a12c9a496875a42a7d70e034fe06d" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", +] [[package]] name = "strsim" @@ -1734,11 +2418,17 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" -version = "2.6.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" @@ -1762,6 +2452,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -1789,9 +2488,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" dependencies = [ "anyhow", - "hmac", + "hmac 0.8.1", "once_cell", - "pbkdf2", + "pbkdf2 0.4.0", "rand 0.7.3", "rustc-hash", "sha2 0.9.9", @@ -1886,6 +2585,26 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "uriparse" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" +dependencies = [ + "fnv", + "lazy_static", +] + [[package]] name = "version_check" version = "0.9.5" @@ -1969,6 +2688,46 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -2042,6 +2801,35 @@ dependencies = [ "memchr", ] +[[package]] +name = "wormhole-anchor-sdk" +version = "0.30.1-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f519ac46a3e5ae1883eb4bb1036421e12e2d21ea917d24aac8df59e82334ee" +dependencies = [ + "anchor-lang", + "anchor-spl", + "cfg-if", + "wormhole-io", +] + +[[package]] +name = "wormhole-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021a14ea7bcef9517ed9f81d4466c4a663dd90e726c5724707a976fa83ad8f3" + +[[package]] +name = "wormhole-reporter" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "message", + "slots", + "wormhole-anchor-sdk", + "wormhole-io", +] + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/packages/solana/programs/wormhole-reporter/Cargo.toml b/packages/solana/programs/wormhole-reporter/Cargo.toml new file mode 100644 index 00000000..21573a5b --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "wormhole-reporter" +version = "0.1.0" +description = "Created with Anchor" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] +name = "wormhole_reporter" + +[features] +default = ["mainnet"] +mainnet = ["wormhole-anchor-sdk/mainnet"] +testnet = ["wormhole-anchor-sdk/solana-devnet"] +devnet = ["wormhole-anchor-sdk/tilt-devnet"] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build", "wormhole-anchor-sdk/idl-build"] + +[dependencies] +anchor-lang = "0.30.1" +slots = { path = "../../shared/slots" } +message = { path = "../../shared/message" } +wormhole-anchor-sdk = "0.30.1-alpha.3" +wormhole-io = "0.1.3" \ No newline at end of file diff --git a/packages/solana/programs/wormhole-reporter/Xargo.toml b/packages/solana/programs/wormhole-reporter/Xargo.toml new file mode 100644 index 00000000..475fb71e --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_slot.rs b/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_slot.rs new file mode 100644 index 00000000..3a98ef51 --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_slot.rs @@ -0,0 +1,85 @@ +use anchor_lang::prelude::*; +use anchor_lang::solana_program::sysvar; +use wormhole_anchor_sdk::wormhole::{self, program::Wormhole}; + +use crate::{ + error::ErrorCode, + state::{Config, WormholeEmitter}, +}; + +/// AKA `b"sent"`. +const SEED_PREFIX_SENT: &[u8; 4] = b"sent"; + +#[derive(Accounts)] +pub struct DispatchSlot<'info> { + #[account(mut)] + /// Payer will pay Wormhole fee to post a message. + pub payer: Signer<'info>, + + #[account( + seeds = [Config::SEED_PREFIX], + bump, + )] + /// Config account. Wormhole PDAs specified in the config are checked + /// against the Wormhole accounts in this context. Read-only. + pub config: Account<'info, Config>, + + /// Wormhole program. + pub wormhole_program: Program<'info, Wormhole>, + + #[account( + mut, + address = config.wormhole.bridge @ ErrorCode::InvalidWormholeConfig + )] + /// Wormhole bridge data. [`wormhole::post_message`] requires this account + /// be mutable. + pub wormhole_bridge: Account<'info, wormhole::BridgeData>, + + #[account( + mut, + address = config.wormhole.fee_collector @ ErrorCode::InvalidWormholeFeeCollector + )] + /// Wormhole fee collector. [`wormhole::post_message`] requires this + /// account be mutable. + pub wormhole_fee_collector: Account<'info, wormhole::FeeCollector>, + + #[account( + seeds = [WormholeEmitter::SEED_PREFIX], + bump, + )] + /// Program's emitter account. Read-only. + pub wormhole_emitter: Account<'info, WormholeEmitter>, + + #[account( + mut, + address = config.wormhole.sequence @ ErrorCode::InvalidWormholeSequence + )] + /// Emitter's sequence account. [`wormhole::post_message`] requires this + /// account be mutable. + pub wormhole_sequence: Account<'info, wormhole::SequenceTracker>, + + #[account( + mut, + seeds = [ + SEED_PREFIX_SENT, + &wormhole_sequence.next_value().to_le_bytes()[..] + ], + bump, + )] + /// CHECK: Wormhole Message. [`wormhole::post_message`] requires this + /// account be mutable. + pub wormhole_message: UncheckedAccount<'info>, + + /// System program. + pub system_program: Program<'info, System>, + + /// Clock sysvar. + pub clock: Sysvar<'info, Clock>, + + /// Rent sysvar. + pub rent: Sysvar<'info, Rent>, + + /// CHECK: We are reading from SlotHashes sysvar the latest slot hash + #[account(address = sysvar::slot_hashes::ID)] + pub slot_hashes: AccountInfo<'info>, +} diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs new file mode 100644 index 00000000..843621e7 --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs @@ -0,0 +1,103 @@ +use anchor_lang::prelude::*; +use wormhole_anchor_sdk::wormhole::{self, program::Wormhole}; + +use crate::state::{Config, WormholeEmitter}; + +/// AKA `b"sent"`. +pub const SEED_PREFIX_SENT: &[u8; 4] = b"sent"; + +#[derive(Accounts)] +/// Context used to initialize program data (i.e. config). +pub struct Initialize<'info> { + #[account(mut)] + /// Whoever initializes the config will be the owner of the program. Signer + /// for creating the [`Config`] account and posting a Wormhole message + /// indicating that the program is alive. + pub owner: Signer<'info>, + + #[account( + init, + payer = owner, + seeds = [Config::SEED_PREFIX], + bump, + space = Config::MAXIMUM_SIZE, + + )] + /// Config account, which saves program data useful for other instructions. + /// Also saves the payer of the [`initialize`](crate::initialize) instruction + /// as the program's owner. + pub config: Account<'info, Config>, + + /// Wormhole program. + pub wormhole_program: Program<'info, Wormhole>, + + #[account( + mut, + seeds = [wormhole::BridgeData::SEED_PREFIX], + bump, + seeds::program = wormhole_program.key, + )] + /// Wormhole bridge data account (a.k.a. its config). + /// [`wormhole::post_message`] requires this account be mutable. + pub wormhole_bridge: Account<'info, wormhole::BridgeData>, + + #[account( + mut, + seeds = [wormhole::FeeCollector::SEED_PREFIX], + bump, + seeds::program = wormhole_program.key + )] + /// Wormhole fee collector account, which requires lamports before the + /// program can post a message (if there is a fee). + /// [`wormhole::post_message`] requires this account be mutable. + pub wormhole_fee_collector: Account<'info, wormhole::FeeCollector>, + + #[account( + init, + payer = owner, + seeds = [WormholeEmitter::SEED_PREFIX], + bump, + space = WormholeEmitter::MAXIMUM_SIZE + )] + /// This program's emitter account. We create this account in the + /// [`initialize`](crate::initialize) instruction, but + /// [`wormhole::post_message`] only needs it to be read-only. + pub wormhole_emitter: Account<'info, WormholeEmitter>, + + #[account( + mut, + seeds = [ + wormhole::SequenceTracker::SEED_PREFIX, + wormhole_emitter.key().as_ref() + ], + bump, + seeds::program = wormhole_program.key + )] + /// CHECK: Emitter's sequence account. This is not created until the first + /// message is posted, so it needs to be an [UncheckedAccount] for the + /// [`initialize`](crate::initialize) instruction. + /// [`wormhole::post_message`] requires this account be mutable. + pub wormhole_sequence: UncheckedAccount<'info>, + + #[account( + mut, + seeds = [ + SEED_PREFIX_SENT, + &wormhole::INITIAL_SEQUENCE.to_le_bytes()[..] + ], + bump, + )] + /// CHECK: Wormhole message account. The Wormhole program writes to this + /// account, which requires this program's signature. + /// [`wormhole::post_message`] requires this account be mutable. + pub wormhole_message: UncheckedAccount<'info>, + + /// Clock sysvar. + pub clock: Sysvar<'info, Clock>, + + /// Rent sysvar. + pub rent: Sysvar<'info, Rent>, + + /// System program. + pub system_program: Program<'info, System>, +} diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/mod.rs b/packages/solana/programs/wormhole-reporter/src/contexts/mod.rs new file mode 100644 index 00000000..24945d67 --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/contexts/mod.rs @@ -0,0 +1,5 @@ +pub mod dispatch_slot; +pub mod initialize; + +pub use dispatch_slot::*; +pub use initialize::*; diff --git a/packages/solana/programs/wormhole-reporter/src/error.rs b/packages/solana/programs/wormhole-reporter/src/error.rs new file mode 100644 index 00000000..16a309ea --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/error.rs @@ -0,0 +1,41 @@ +use anchor_lang::prelude::error_code; + +#[error_code] +/// Errors relevant to this program's malfunction. +pub enum ErrorCode { + #[msg("InvalidWormholeConfig")] + /// Specified Wormhole bridge data PDA is wrong. + InvalidWormholeConfig, + + #[msg("InvalidWormholeFeeCollector")] + /// Specified Wormhole fee collector PDA is wrong. + InvalidWormholeFeeCollector, + + #[msg("InvalidWormholeEmitter")] + /// Specified program's emitter PDA is wrong. + InvalidWormholeEmitter, + + #[msg("InvalidWormholeSequence")] + /// Specified emitter's sequence PDA is wrong. + InvalidWormholeSequence, + + #[msg("InvalidSysvar")] + /// Specified sysvar is wrong. + InvalidSysvar, + + #[msg("OwnerOnly")] + /// Only the program's owner is permitted. + OwnerOnly, + + #[msg("InvalidForeignEmitter")] + /// Specified foreign emitter has a bad chain ID or zero address. + InvalidForeignEmitter, + + #[msg("BumpNotFound")] + /// Bump not found in `bumps` map. + BumpNotFound, + + #[msg("InvalidMessage")] + /// Deserialized message has unexpected payload type. + InvalidMessage, +} diff --git a/packages/solana/programs/wormhole-reporter/src/lib.rs b/packages/solana/programs/wormhole-reporter/src/lib.rs new file mode 100644 index 00000000..7a64c092 --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/lib.rs @@ -0,0 +1,150 @@ +use anchor_lang::prelude::*; + +pub mod contexts; +pub mod error; +pub mod state; + +pub use contexts::*; +pub use error::ErrorCode; +pub use state::*; + +declare_id!("4y9MQDaWZrfghUAJPmm9uJwCEyZzNZSzPVxs1WKbMXbn"); + +#[program] +pub mod wormhole_reporter { + use super::*; + use anchor_lang::solana_program; + use message::Message; + use slots::get_slot; + use wormhole_anchor_sdk::wormhole; + + /// This instruction initializes the program config, which is meant + /// to store data useful for other instructions. The config specifies + /// an owner (e.g. multisig) and should be read-only for every instruction + /// in this example. This owner will be checked for designated owner-only + /// instructions like [`register_emitter`](register_emitter). + /// + /// # Arguments + /// + /// * `ctx` - `Initialize` contexts + pub fn initialize(ctx: Context) -> Result<()> { + let config = &mut ctx.accounts.config; + + // Set the owner of the config (effectively the owner of the program). + config.owner = ctx.accounts.owner.key(); + + // Set Wormhole related addresses. + { + let wormhole = &mut config.wormhole; + + // wormhole::BridgeData (Wormhole's program data). + wormhole.bridge = ctx.accounts.wormhole_bridge.key(); + + // wormhole::FeeCollector (lamports collector for posting + // messages). + wormhole.fee_collector = ctx.accounts.wormhole_fee_collector.key(); + + // wormhole::SequenceTracker (tracks # of messages posted by this + // program). + wormhole.sequence = ctx.accounts.wormhole_sequence.key(); + } + + // Set default values for posting Wormhole messages. + // + // Zero means no batching. + config.batch_id = 0; + + // Anchor IDL default coder cannot handle wormhole::Finality enum, + // so this value is stored as u8. + config.finality = wormhole::Finality::Confirmed as u8; + + // Initialize our Wormhole emitter account. It is not required by the + // Wormhole program that there is an actual account associated with the + // emitter PDA. The emitter PDA is just a mechanism to have the program + // sign for the `wormhole::post_message` instruction. + // + // But for fun, we will store our emitter's bump for convenience. + ctx.accounts.wormhole_emitter.bump = ctx.bumps.wormhole_emitter; + + // Done. + Ok(()) + } + + pub fn dispatch_slot( + ctx: Context, + target_chain_id: [u8; 32], + receiver: Vec, + slot_number: u64, + ) -> Result<()> { + // If Wormhole requires a fee before posting a message, we need to + // transfer lamports to the fee collector. Otherwise + // `wormhole::post_message` will fail. + let fee = ctx.accounts.wormhole_bridge.fee(); + if fee > 0 { + solana_program::program::invoke( + &solana_program::system_instruction::transfer( + &ctx.accounts.payer.key(), + &ctx.accounts.wormhole_fee_collector.key(), + fee, + ), + &ctx.accounts.to_account_infos(), + )?; + } + + // Invoke `wormhole::post_message`. + // + // `wormhole::post_message` requires two signers: one for the emitter + // and another for the wormhole message data. Both of these accounts + // are owned by this program. + // + // There are two ways to handle the wormhole message data account: + // 1. Using an extra keypair. You may to generate a keypair outside + // of this instruction and pass that keypair as an additional + // signer for the transaction. An integrator might use an extra + // keypair if the message can be "thrown away" (not easily + // retrievable without going back to this transaction hash to + // retrieve the message's pubkey). + // 2. Generate a PDA. If we want some way to deserialize the message + // data written by the Wormhole program, we can use an account + // with an address derived by this program so we can use the PDA + // to access and deserialize the message data. + // + // we use method #2. + let wormhole_emitter = &ctx.accounts.wormhole_emitter; + let config = &ctx.accounts.config; + + let slot_hash = get_slot(&ctx.accounts.slot_hashes, slot_number)?; + let message = Message::from((slot_number, slot_hash)); + let payload = message.try_to_vec()?; + + wormhole::post_message( + CpiContext::new_with_signer( + ctx.accounts.wormhole_program.to_account_info(), + wormhole::PostMessage { + config: ctx.accounts.wormhole_bridge.to_account_info(), + message: ctx.accounts.wormhole_message.to_account_info(), + emitter: wormhole_emitter.to_account_info(), + sequence: ctx.accounts.wormhole_sequence.to_account_info(), + payer: ctx.accounts.payer.to_account_info(), + fee_collector: ctx.accounts.wormhole_fee_collector.to_account_info(), + clock: ctx.accounts.clock.to_account_info(), + rent: ctx.accounts.rent.to_account_info(), + system_program: ctx.accounts.system_program.to_account_info(), + }, + &[ + &[ + SEED_PREFIX_SENT, + &ctx.accounts.wormhole_sequence.next_value().to_le_bytes()[..], + &[ctx.bumps.wormhole_message], + ], + &[wormhole::SEED_PREFIX_EMITTER, &[wormhole_emitter.bump]], + ], + ), + config.batch_id, + payload, + config.finality.try_into().unwrap(), + )?; + + Ok(()) + } +} diff --git a/packages/solana/programs/wormhole-reporter/src/message.rs b/packages/solana/programs/wormhole-reporter/src/message.rs new file mode 100644 index 00000000..abcae213 --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/message.rs @@ -0,0 +1,206 @@ +use anchor_lang::{prelude::Pubkey, AnchorDeserialize, AnchorSerialize}; +use std::io; +use wormhole_io::Readable; + +const PAYLOAD_ID_ALIVE: u8 = 0; +const PAYLOAD_ID_HELLO: u8 = 1; + +pub const HELLO_MESSAGE_MAX_LENGTH: usize = 512; + +#[derive(Clone)] +/// Expected message types for this program. Only valid payloads are: +/// * `Alive`: Payload ID == 0. Emitted when [`initialize`](crate::initialize) +/// is called). +/// * `Hello`: Payload ID == 1. Emitted when +/// [`send_message`](crate::send_message) is called). +/// +/// Payload IDs are encoded as u8. +pub enum HelloWorldMessage { + Alive { program_id: Pubkey }, + Hello { message: Vec }, +} + +impl AnchorSerialize for HelloWorldMessage { + fn serialize(&self, writer: &mut W) -> io::Result<()> { + match self { + HelloWorldMessage::Alive { program_id } => { + PAYLOAD_ID_ALIVE.serialize(writer)?; + program_id.serialize(writer) + } + HelloWorldMessage::Hello { message } => { + if message.len() > HELLO_MESSAGE_MAX_LENGTH { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("message exceeds {HELLO_MESSAGE_MAX_LENGTH} bytes"), + )) + } else { + PAYLOAD_ID_HELLO.serialize(writer)?; + (message.len() as u16).to_be_bytes().serialize(writer)?; + for item in message { + item.serialize(writer)?; + } + Ok(()) + } + } + } + } +} + +impl AnchorDeserialize for HelloWorldMessage { + fn deserialize_reader(reader: &mut R) -> io::Result { + match u8::read(reader)? { + PAYLOAD_ID_ALIVE => Ok(HelloWorldMessage::Alive { + program_id: Pubkey::try_from(<[u8; 32]>::read(reader)?).unwrap(), + }), + PAYLOAD_ID_HELLO => { + let length = u16::read(reader)? as usize; + if length > HELLO_MESSAGE_MAX_LENGTH { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("message exceeds {HELLO_MESSAGE_MAX_LENGTH} bytes"), + )) + } else { + let mut buf = vec![0; length]; + reader.read_exact(&mut buf)?; + Ok(HelloWorldMessage::Hello { message: buf }) + } + } + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "invalid payload ID", + )), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use anchor_lang::prelude::Result; + use std::{mem::size_of, str, string::String}; + + #[test] + fn test_message_alive() -> Result<()> { + let my_program_id = Pubkey::new_unique(); + let msg = HelloWorldMessage::Alive { + program_id: my_program_id, + }; + + // Serialize program ID above. + let mut encoded = Vec::new(); + msg.serialize(&mut encoded)?; + + assert_eq!(encoded.len(), size_of::() + size_of::()); + + // Verify Payload ID. + assert_eq!(encoded[0], PAYLOAD_ID_ALIVE); + + // Verify Program ID. + let mut program_id_bytes = [0u8; 32]; + program_id_bytes.copy_from_slice(&encoded[1..33]); + assert_eq!(program_id_bytes, my_program_id.to_bytes()); + + // Now deserialize the encoded message. + match HelloWorldMessage::deserialize(&mut encoded.as_slice())? { + HelloWorldMessage::Alive { program_id } => { + assert_eq!(program_id, my_program_id) + } + _ => assert!(false, "incorrect deserialization"), + } + + Ok(()) + } + + #[test] + fn test_message_hello() -> Result<()> { + let raw_message = String::from("All your base are belong to us"); + let msg = HelloWorldMessage::Hello { + message: raw_message.as_bytes().to_vec(), + }; + + // Serialize message above. + let mut encoded = Vec::new(); + msg.serialize(&mut encoded)?; + + assert_eq!( + encoded.len(), + size_of::() + size_of::() + raw_message.len() + ); + + // Verify Payload ID. + assert_eq!(encoded[0], PAYLOAD_ID_HELLO); + + // Verify message length. + let mut message_len_bytes = [0u8; 2]; + message_len_bytes.copy_from_slice(&encoded[1..3]); + assert_eq!( + u16::from_be_bytes(message_len_bytes) as usize, + raw_message.len() + ); + + // Verify message. + let from_utf8_result = str::from_utf8(&encoded[3..]); + assert!(from_utf8_result.is_ok(), "from_utf8 resulted in an error"); + assert_eq!(from_utf8_result.unwrap(), raw_message); + + // Now deserialize the encoded message. + match HelloWorldMessage::deserialize(&mut encoded.as_slice())? { + HelloWorldMessage::Hello { message } => { + assert_eq!(message, raw_message.as_bytes()) + } + _ => assert!(false, "incorrect deserialization"), + } + + Ok(()) + } + + #[test] + fn test_message_hello_too_large() -> Result<()> { + let n: usize = 513; + let raw_message = { + let mut out = Vec::with_capacity(n); + for _ in 0..n { + out.push(33u8) + } + String::from_utf8(out).unwrap() + }; + let msg = HelloWorldMessage::Hello { + message: raw_message.as_bytes().to_vec(), + }; + + // Attempt to serialize message above. + let mut encoded = Vec::new(); + match msg.serialize(&mut encoded) { + Err(e) => assert_eq!(e.kind(), io::ErrorKind::InvalidInput), + _ => assert!(false, "not supposed to serialize"), + }; + + // Serialize manually and then attempt to deserialize. + encoded.push(PAYLOAD_ID_HELLO); + encoded.extend_from_slice(&(raw_message.len() as u16).to_be_bytes()); + encoded.extend_from_slice(raw_message.as_bytes()); + + assert_eq!( + encoded.len(), + size_of::() + size_of::() + raw_message.len() + ); + + // Verify Payload ID. + assert_eq!(encoded[0], PAYLOAD_ID_HELLO); + + // Verify message length. + let mut message_len_bytes = [0u8; 2]; + message_len_bytes.copy_from_slice(&encoded[1..3]); + assert_eq!( + u16::from_be_bytes(message_len_bytes) as usize, + raw_message.len() + ); + + match HelloWorldMessage::deserialize(&mut encoded.as_slice()) { + Err(e) => assert_eq!(e.kind(), io::ErrorKind::InvalidInput), + _ => assert!(false, "not supposed to deserialize"), + }; + + Ok(()) + } +} diff --git a/packages/solana/programs/wormhole-reporter/src/state/config.rs b/packages/solana/programs/wormhole-reporter/src/state/config.rs new file mode 100644 index 00000000..cd22a1df --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/state/config.rs @@ -0,0 +1,48 @@ +use anchor_lang::prelude::*; + +#[derive(Default, AnchorSerialize, AnchorDeserialize, Clone, PartialEq, Eq)] +/// Wormhole program related addresses. +pub struct WormholeAddresses { + /// [BridgeData](wormhole_anchor_sdk::wormhole::BridgeData) address. + pub bridge: Pubkey, + /// [FeeCollector](wormhole_anchor_sdk::wormhole::FeeCollector) address. + pub fee_collector: Pubkey, + /// [SequenceTracker](wormhole_anchor_sdk::wormhole::SequenceTracker) address. + pub sequence: Pubkey, +} + +impl WormholeAddresses { + pub const LEN: usize = + 32 // config + + 32 // fee_collector + + 32 // sequence + ; +} + +#[account] +#[derive(Default)] +/// Config account data. +pub struct Config { + /// Program's owner. + pub owner: Pubkey, + /// Wormhole program's relevant addresses. + pub wormhole: WormholeAddresses, + /// AKA nonce. Just zero, but saving this information in this account + /// anyway. + pub batch_id: u32, + /// AKA consistency level. u8 representation of Solana's + /// [Finality](wormhole_anchor_sdk::wormhole::Finality). + pub finality: u8, +} + +impl Config { + pub const MAXIMUM_SIZE: usize = 8 // discriminator + + 32 // owner + + WormholeAddresses::LEN + + 4 // batch_id + + 1 // finality + + ; + /// AKA `b"config"`. + pub const SEED_PREFIX: &'static [u8; 6] = b"config"; +} \ No newline at end of file diff --git a/packages/solana/programs/wormhole-reporter/src/state/mod.rs b/packages/solana/programs/wormhole-reporter/src/state/mod.rs new file mode 100644 index 00000000..cd7e0413 --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/state/mod.rs @@ -0,0 +1,5 @@ +pub use config::*; +pub use wormhole_emitter::*; + +pub mod config; +pub mod wormhole_emitter; diff --git a/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs b/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs new file mode 100644 index 00000000..36007a7e --- /dev/null +++ b/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs @@ -0,0 +1,35 @@ +use anchor_lang::prelude::*; +use wormhole_anchor_sdk::wormhole; + +#[account] +#[derive(Default)] +/// Wormhole emitter account. +pub struct WormholeEmitter { + /// PDA bump. + pub bump: u8, +} + +impl WormholeEmitter { + pub const MAXIMUM_SIZE: usize = 8 // discriminator + + 1 // bump + ; + /// AKA `b"emitter` (see + /// [`SEED_PREFIX_EMITTER`](wormhole::SEED_PREFIX_EMITTER)). + pub const SEED_PREFIX: &'static [u8; 7] = wormhole::SEED_PREFIX_EMITTER; +} + +#[cfg(test)] +mod test { + use super::*; + use std::mem::size_of; + + #[test] + fn test_wormhole_emitter() -> Result<()> { + assert_eq!( + WormholeEmitter::MAXIMUM_SIZE, + size_of::() + size_of::() + ); + + Ok(()) + } +} From fd82a9f47733d6b6a03fe3eac84a3f577f75a821 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Mon, 2 Dec 2024 06:33:28 +0100 Subject: [PATCH 09/31] chore(solana): rm not used file --- .../programs/wormhole-reporter/src/message.rs | 206 ------------------ 1 file changed, 206 deletions(-) delete mode 100644 packages/solana/programs/wormhole-reporter/src/message.rs diff --git a/packages/solana/programs/wormhole-reporter/src/message.rs b/packages/solana/programs/wormhole-reporter/src/message.rs deleted file mode 100644 index abcae213..00000000 --- a/packages/solana/programs/wormhole-reporter/src/message.rs +++ /dev/null @@ -1,206 +0,0 @@ -use anchor_lang::{prelude::Pubkey, AnchorDeserialize, AnchorSerialize}; -use std::io; -use wormhole_io::Readable; - -const PAYLOAD_ID_ALIVE: u8 = 0; -const PAYLOAD_ID_HELLO: u8 = 1; - -pub const HELLO_MESSAGE_MAX_LENGTH: usize = 512; - -#[derive(Clone)] -/// Expected message types for this program. Only valid payloads are: -/// * `Alive`: Payload ID == 0. Emitted when [`initialize`](crate::initialize) -/// is called). -/// * `Hello`: Payload ID == 1. Emitted when -/// [`send_message`](crate::send_message) is called). -/// -/// Payload IDs are encoded as u8. -pub enum HelloWorldMessage { - Alive { program_id: Pubkey }, - Hello { message: Vec }, -} - -impl AnchorSerialize for HelloWorldMessage { - fn serialize(&self, writer: &mut W) -> io::Result<()> { - match self { - HelloWorldMessage::Alive { program_id } => { - PAYLOAD_ID_ALIVE.serialize(writer)?; - program_id.serialize(writer) - } - HelloWorldMessage::Hello { message } => { - if message.len() > HELLO_MESSAGE_MAX_LENGTH { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("message exceeds {HELLO_MESSAGE_MAX_LENGTH} bytes"), - )) - } else { - PAYLOAD_ID_HELLO.serialize(writer)?; - (message.len() as u16).to_be_bytes().serialize(writer)?; - for item in message { - item.serialize(writer)?; - } - Ok(()) - } - } - } - } -} - -impl AnchorDeserialize for HelloWorldMessage { - fn deserialize_reader(reader: &mut R) -> io::Result { - match u8::read(reader)? { - PAYLOAD_ID_ALIVE => Ok(HelloWorldMessage::Alive { - program_id: Pubkey::try_from(<[u8; 32]>::read(reader)?).unwrap(), - }), - PAYLOAD_ID_HELLO => { - let length = u16::read(reader)? as usize; - if length > HELLO_MESSAGE_MAX_LENGTH { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("message exceeds {HELLO_MESSAGE_MAX_LENGTH} bytes"), - )) - } else { - let mut buf = vec![0; length]; - reader.read_exact(&mut buf)?; - Ok(HelloWorldMessage::Hello { message: buf }) - } - } - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "invalid payload ID", - )), - } - } -} - -#[cfg(test)] -mod test { - use super::*; - use anchor_lang::prelude::Result; - use std::{mem::size_of, str, string::String}; - - #[test] - fn test_message_alive() -> Result<()> { - let my_program_id = Pubkey::new_unique(); - let msg = HelloWorldMessage::Alive { - program_id: my_program_id, - }; - - // Serialize program ID above. - let mut encoded = Vec::new(); - msg.serialize(&mut encoded)?; - - assert_eq!(encoded.len(), size_of::() + size_of::()); - - // Verify Payload ID. - assert_eq!(encoded[0], PAYLOAD_ID_ALIVE); - - // Verify Program ID. - let mut program_id_bytes = [0u8; 32]; - program_id_bytes.copy_from_slice(&encoded[1..33]); - assert_eq!(program_id_bytes, my_program_id.to_bytes()); - - // Now deserialize the encoded message. - match HelloWorldMessage::deserialize(&mut encoded.as_slice())? { - HelloWorldMessage::Alive { program_id } => { - assert_eq!(program_id, my_program_id) - } - _ => assert!(false, "incorrect deserialization"), - } - - Ok(()) - } - - #[test] - fn test_message_hello() -> Result<()> { - let raw_message = String::from("All your base are belong to us"); - let msg = HelloWorldMessage::Hello { - message: raw_message.as_bytes().to_vec(), - }; - - // Serialize message above. - let mut encoded = Vec::new(); - msg.serialize(&mut encoded)?; - - assert_eq!( - encoded.len(), - size_of::() + size_of::() + raw_message.len() - ); - - // Verify Payload ID. - assert_eq!(encoded[0], PAYLOAD_ID_HELLO); - - // Verify message length. - let mut message_len_bytes = [0u8; 2]; - message_len_bytes.copy_from_slice(&encoded[1..3]); - assert_eq!( - u16::from_be_bytes(message_len_bytes) as usize, - raw_message.len() - ); - - // Verify message. - let from_utf8_result = str::from_utf8(&encoded[3..]); - assert!(from_utf8_result.is_ok(), "from_utf8 resulted in an error"); - assert_eq!(from_utf8_result.unwrap(), raw_message); - - // Now deserialize the encoded message. - match HelloWorldMessage::deserialize(&mut encoded.as_slice())? { - HelloWorldMessage::Hello { message } => { - assert_eq!(message, raw_message.as_bytes()) - } - _ => assert!(false, "incorrect deserialization"), - } - - Ok(()) - } - - #[test] - fn test_message_hello_too_large() -> Result<()> { - let n: usize = 513; - let raw_message = { - let mut out = Vec::with_capacity(n); - for _ in 0..n { - out.push(33u8) - } - String::from_utf8(out).unwrap() - }; - let msg = HelloWorldMessage::Hello { - message: raw_message.as_bytes().to_vec(), - }; - - // Attempt to serialize message above. - let mut encoded = Vec::new(); - match msg.serialize(&mut encoded) { - Err(e) => assert_eq!(e.kind(), io::ErrorKind::InvalidInput), - _ => assert!(false, "not supposed to serialize"), - }; - - // Serialize manually and then attempt to deserialize. - encoded.push(PAYLOAD_ID_HELLO); - encoded.extend_from_slice(&(raw_message.len() as u16).to_be_bytes()); - encoded.extend_from_slice(raw_message.as_bytes()); - - assert_eq!( - encoded.len(), - size_of::() + size_of::() + raw_message.len() - ); - - // Verify Payload ID. - assert_eq!(encoded[0], PAYLOAD_ID_HELLO); - - // Verify message length. - let mut message_len_bytes = [0u8; 2]; - message_len_bytes.copy_from_slice(&encoded[1..3]); - assert_eq!( - u16::from_be_bytes(message_len_bytes) as usize, - raw_message.len() - ); - - match HelloWorldMessage::deserialize(&mut encoded.as_slice()) { - Err(e) => assert_eq!(e.kind(), io::ErrorKind::InvalidInput), - _ => assert!(false, "not supposed to deserialize"), - }; - - Ok(()) - } -} From 70f14cf855cc92c82a54a827f4cc6ec962025f73 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Thu, 5 Dec 2024 06:34:24 +0100 Subject: [PATCH 10/31] feat(solana): adds abi encoding for message and adds tests for wormhole reporter --- packages/solana/Anchor.toml | 28 +- packages/solana/Cargo.lock | 983 +++++++++- packages/solana/Cargo.toml | 8 + packages/solana/package.json | 14 +- .../programs/wormhole-reporter/Cargo.toml | 6 +- .../programs/wormhole-reporter/src/lib.rs | 110 +- .../src/state/wormhole_emitter.rs | 16 - packages/solana/shared/message/Cargo.toml | 2 + packages/solana/shared/message/src/lib.rs | 56 +- packages/solana/tests/wormhole-reporter.ts | 103 + packages/solana/tsconfig.json | 6 +- yarn.lock | 1719 ++++++++++++++++- 12 files changed, 2854 insertions(+), 197 deletions(-) create mode 100644 packages/solana/tests/wormhole-reporter.ts diff --git a/packages/solana/Anchor.toml b/packages/solana/Anchor.toml index 325f23c8..59f0df86 100644 --- a/packages/solana/Anchor.toml +++ b/packages/solana/Anchor.toml @@ -5,12 +5,10 @@ resolution = true skip-lint = false [programs.localnet] -debridge-reporter = "2TvQ6gqQGAifdV2cQ1f8zHGYV2t6wPUNTKzpcALt8rX7" -hashi = "EyqiZf8Yt2CgVU5yPsj5e4EiGXeKrLhefWBn7CSqKPMC" -help = "EJy8wh5fqP5LYqs1mNbH2S6jxKGkP64PkXRmZgQxk9CE" -reporter = "4wFzP8uwPvvW2kZGxxkL45SP2Wn3oRbfe1LdHheUFZ9k" -solana = "4VFxPo4BF53PkVFBFjCQBFUn8bCxZZm6Dc2VgrJ5HXS8" -wormhole-reporter = "4y9MQDaWZrfghUAJPmm9uJwCEyZzNZSzPVxs1WKbMXbn" +adapter = "EUDyxkHVf9NBRTREn69rcFDAEefmHj3UrLJV14vnqACp" +debridge-reporter = "7GPwvvhq33fTYuDyfA1JVz4fp3XkdcmjerJWpUkxjrC2" +hashi = "76cEKq1qRhBLn56kZdG1Hj7UHXggcNfinbnKejXDnMpU" +wormhole-reporter = "3ESz1nYWmkdp9A3SByK7mbf9toDSRPvJADDF6pz45qZG" [registry] url = "https://api.apr.dev" @@ -21,3 +19,21 @@ wallet = "~/.config/solana/id.json" [scripts] test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" + +[test] +startup_wait = 10000 + +[test.validator] +url = "https://api.mainnet-beta.solana.com" + +### Wormhole Core Bridge +[[test.validator.clone]] +address = "worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth" + +### Wormhole Bridge +[[test.validator.clone]] +address = "2yVjuQwpsvdsrywzsJJVs9Ueh4zayyo5DYJbBNc3DDpn" + +### Wormhole Fee Collector +[[test.validator.clone]] +address = "9bFNrXNb2WTx8fMHXCheaZqkLZ3YCCaiqTftHxeintHy" \ No newline at end of file diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index 7e3de302..248247d3 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -33,8 +33,7 @@ dependencies = [ [[package]] name = "aes-gcm-siv" version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" +source = "git+https://github.com/RustCrypto/AEADs?rev=6105d7a5591aefa646a95d12b5e8d3f55a9214ef#6105d7a5591aefa646a95d12b5e8d3f55a9214ef" dependencies = [ "aead", "aes", @@ -77,6 +76,97 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloy-primitives" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand 0.8.5", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0822426598f95e45dd1ea32a738dac057529a709ee645fcc516ffa4cbde08f" +dependencies = [ + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck 0.5.0", + "indexmap", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.90", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" +dependencies = [ + "const-hex", + "dunce", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.90", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-types" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" +dependencies = [ + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + [[package]] name = "anchor-attribute-access-control" version = "0.30.1" @@ -146,7 +236,7 @@ dependencies = [ "anchor-syn", "anyhow", "bs58 0.5.1", - "heck", + "heck 0.3.3", "proc-macro2", "quote", "serde_json", @@ -222,7 +312,7 @@ checksum = "31cf97b4e6f7d6144a05e435660fcf757dbc3446d38d0e2b851d11ed13625bba" dependencies = [ "anchor-lang-idl-spec", "anyhow", - "heck", + "heck 0.3.3", "regex", "serde", "serde_json", @@ -264,7 +354,7 @@ dependencies = [ "anyhow", "bs58 0.5.1", "cargo_toml", - "heck", + "heck 0.3.3", "proc-macro2", "quote", "serde", @@ -276,9 +366,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "ark-bn254" @@ -287,8 +377,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" dependencies = [ "ark-ec", - "ark-ff", - "ark-std", + "ark-ff 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -297,10 +387,10 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" dependencies = [ - "ark-ff", + "ark-ff 0.4.2", "ark-poly", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", "itertools", @@ -308,26 +398,54 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + [[package]] name = "ark-ff" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "digest 0.10.7", "itertools", "num-bigint", "num-traits", "paste", - "rustc_version", + "rustc_version 0.4.1", "zeroize", ] +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-asm" version = "0.4.2" @@ -338,6 +456,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-macros" version = "0.4.2" @@ -357,13 +487,23 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", ] +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + [[package]] name = "ark-serialize" version = "0.4.2" @@ -371,7 +511,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ "ark-serialize-derive", - "ark-std", + "ark-std 0.4.0", "digest 0.10.7", "num-bigint", ] @@ -387,6 +527,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "ark-std" version = "0.4.0" @@ -426,12 +576,29 @@ dependencies = [ "winapi", ] +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.12.3" @@ -450,6 +617,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bincode" version = "1.3.3" @@ -459,6 +632,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "2.6.0" @@ -477,11 +665,23 @@ dependencies = [ "typenum", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" dependencies = [ "arrayref", "arrayvec", @@ -582,7 +782,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -660,6 +860,12 @@ dependencies = [ "serde", ] +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + [[package]] name = "bytemuck" version = "1.20.0" @@ -677,7 +883,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -686,6 +892,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + [[package]] name = "cargo_toml" version = "0.19.2" @@ -698,9 +910,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "jobserver", "libc", @@ -763,12 +975,37 @@ dependencies = [ "web-sys", ] +[[package]] +name = "const-hex" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "constant_time_eq" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +[[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.16" @@ -809,6 +1046,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -841,8 +1090,7 @@ dependencies = [ [[package]] name = "curve25519-dalek" version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +source = "git+https://github.com/solana-labs/curve25519-dalek.git?rev=b500cdc2a920cd5bff9e2dd974d7b97349d61464#b500cdc2a920cd5bff9e2dd974d7b97349d61464" dependencies = [ "byteorder", "digest 0.9.0", @@ -897,7 +1145,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -919,7 +1167,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -949,6 +1197,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "derivation-path" version = "0.2.0" @@ -997,6 +1255,19 @@ dependencies = [ "syn 1.0.109", ] +[[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 0.4.1", + "syn 2.0.90", +] + [[package]] name = "digest" version = "0.9.0" @@ -1013,17 +1284,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature 2.2.0", + "spki", +] + [[package]] name = "ed25519" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ - "signature", + "signature 1.6.4", ] [[package]] @@ -1058,6 +1350,25 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "env_logger" version = "0.9.3" @@ -1091,18 +1402,73 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fastrand" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "feature-probe" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "generic-array" version = "0.14.7" @@ -1112,6 +1478,7 @@ dependencies = [ "serde", "typenum", "version_check", + "zeroize", ] [[package]] @@ -1140,6 +1507,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -1181,6 +1559,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1196,6 +1580,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + [[package]] name = "hmac" version = "0.8.1" @@ -1254,11 +1644,31 @@ dependencies = [ "version_check", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1290,13 +1700,27 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" dependencies = [ + "once_cell", "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.8", +] + [[package]] name = "keccak" version = "0.1.5" @@ -1306,6 +1730,16 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1314,9 +1748,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.165" +version = "0.2.167" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" + +[[package]] +name = "libm" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb4d3d38eab6c5239a362fa8bae48c03baf980a6e7079f063942d563ef3533e" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libsecp256k1" @@ -1373,11 +1813,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" dependencies = [ "ark-bn254", - "ark-ff", + "ark-ff 0.4.2", "num-bigint", "thiserror", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "lock_api" version = "0.4.12" @@ -1434,6 +1880,8 @@ dependencies = [ name = "message" version = "0.1.0" dependencies = [ + "alloy-primitives", + "alloy-sol-types", "anchor-lang", ] @@ -1479,7 +1927,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1498,6 +1946,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1518,7 +1967,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1533,6 +1982,32 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -1586,6 +2061,27 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "polyval" version = "0.5.3" @@ -1607,6 +2103,17 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -1625,6 +2132,30 @@ dependencies = [ "toml_edit", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "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]] name = "proc-macro2" version = "1.0.92" @@ -1634,6 +2165,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + [[package]] name = "qstring" version = "0.7.2" @@ -1651,9 +2202,15 @@ checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.37" @@ -1663,6 +2220,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.7.3" @@ -1734,6 +2297,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rand_xoshiro" version = "0.6.0" @@ -1801,19 +2373,97 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "ruint" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand 0.8.5", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.23", +] + +[[package]] +name = "rustix" +version = "0.38.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1822,6 +2472,18 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.18" @@ -1834,12 +2496,44 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.215" @@ -1866,7 +2560,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1909,7 +2603,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1958,6 +2652,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1970,6 +2674,16 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -2014,7 +2728,7 @@ dependencies = [ "lazy_static", "log", "memmap2", - "rustc_version", + "rustc_version 0.4.1", "serde", "serde_bytes", "serde_derive", @@ -2032,8 +2746,8 @@ checksum = "c142f779c3633ac83c84d04ff06c70e1f558c876f13358bed77ba629c7417932" dependencies = [ "proc-macro2", "quote", - "rustc_version", - "syn 2.0.89", + "rustc_version 0.4.1", + "syn 2.0.90", ] [[package]] @@ -2055,8 +2769,8 @@ checksum = "c10f4588cefd716b24a1a40dd32c278e43a560ab8ce4de6b5805c9d113afdfa1" dependencies = [ "ark-bn254", "ark-ec", - "ark-ff", - "ark-serialize", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", "base64 0.21.7", "bincode", "bitflags", @@ -2085,7 +2799,7 @@ dependencies = [ "num-traits", "parking_lot", "rand 0.8.5", - "rustc_version", + "rustc_version 0.4.1", "rustversion", "serde", "serde_bytes", @@ -2137,7 +2851,7 @@ dependencies = [ "qualifier_attr", "rand 0.7.3", "rand 0.8.5", - "rustc_version", + "rustc_version 0.4.1", "rustversion", "serde", "serde_bytes", @@ -2167,7 +2881,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2205,6 +2919,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "spl-associated-token-account" version = "3.0.4" @@ -2240,7 +2964,7 @@ checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" dependencies = [ "quote", "spl-discriminator-syn", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2252,7 +2976,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.8", - "syn 2.0.89", + "syn 2.0.90", "thiserror", ] @@ -2300,7 +3024,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.8", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2412,6 +3136,12 @@ dependencies = [ "spl-program-error", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.10.0" @@ -2443,15 +3173,46 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "syn-solidity" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c837dc8852cb7074e46b444afb81783140dab12c58867b49fb3898fbafedf7ea" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -2478,7 +3239,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2500,6 +3261,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -2564,6 +3334,30 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-ident" version = "1.0.14" @@ -2605,12 +3399,27 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -2625,9 +3434,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" dependencies = [ "cfg-if", "once_cell", @@ -2636,24 +3445,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2661,28 +3470,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" dependencies = [ "js-sys", "wasm-bindgen", @@ -2710,7 +3519,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -2719,6 +3528,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.59.0" @@ -2830,6 +3648,15 @@ dependencies = [ "wormhole-io", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -2848,14 +3675,14 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "zeroize" -version = "1.3.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -2868,5 +3695,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] diff --git a/packages/solana/Cargo.toml b/packages/solana/Cargo.toml index e151e9d4..c018f5ae 100644 --- a/packages/solana/Cargo.toml +++ b/packages/solana/Cargo.toml @@ -13,3 +13,11 @@ codegen-units = 1 opt-level = 3 incremental = false codegen-units = 1 + +[patch.crates-io.aes-gcm-siv] +git = "https://github.com/RustCrypto/AEADs" +rev = "6105d7a5591aefa646a95d12b5e8d3f55a9214ef" + +[patch.crates-io.curve25519-dalek] +git = "https://github.com/solana-labs/curve25519-dalek.git" +rev = "b500cdc2a920cd5bff9e2dd974d7b97349d61464" \ No newline at end of file diff --git a/packages/solana/package.json b/packages/solana/package.json index 31a0ff57..b9e78d31 100644 --- a/packages/solana/package.json +++ b/packages/solana/package.json @@ -7,16 +7,18 @@ "prettier:write": "prettier --write \"**/*.{js,json,md,ts,yml}\"" }, "dependencies": { - "@coral-xyz/anchor": "^0.30.1" + "@certusone/wormhole-sdk": "^0.10.18", + "@coral-xyz/anchor": "^0.30.1", + "ethers": "^6.13.4" }, "devDependencies": { - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", "@types/bn.js": "^5.1.0", "@types/chai": "^4.3.0", "@types/mocha": "^9.0.0", - "typescript": "^4.3.5", - "prettier": "^2.6.2" + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^4.3.5" } } diff --git a/packages/solana/programs/wormhole-reporter/Cargo.toml b/packages/solana/programs/wormhole-reporter/Cargo.toml index 21573a5b..78e33669 100644 --- a/packages/solana/programs/wormhole-reporter/Cargo.toml +++ b/packages/solana/programs/wormhole-reporter/Cargo.toml @@ -12,7 +12,7 @@ name = "wormhole_reporter" default = ["mainnet"] mainnet = ["wormhole-anchor-sdk/mainnet"] testnet = ["wormhole-anchor-sdk/solana-devnet"] -devnet = ["wormhole-anchor-sdk/tilt-devnet"] +localnet = ["wormhole-anchor-sdk/tilt-devnet"] cpi = ["no-entrypoint"] no-entrypoint = [] no-idl = [] @@ -23,5 +23,5 @@ idl-build = ["anchor-lang/idl-build", "wormhole-anchor-sdk/idl-build"] anchor-lang = "0.30.1" slots = { path = "../../shared/slots" } message = { path = "../../shared/message" } -wormhole-anchor-sdk = "0.30.1-alpha.3" -wormhole-io = "0.1.3" \ No newline at end of file +wormhole-anchor-sdk = { version = "0.30.1-alpha.3", default-features = false } +wormhole-io = "0.1.3" diff --git a/packages/solana/programs/wormhole-reporter/src/lib.rs b/packages/solana/programs/wormhole-reporter/src/lib.rs index 7a64c092..7e2c7c39 100644 --- a/packages/solana/programs/wormhole-reporter/src/lib.rs +++ b/packages/solana/programs/wormhole-reporter/src/lib.rs @@ -8,7 +8,7 @@ pub use contexts::*; pub use error::ErrorCode; pub use state::*; -declare_id!("4y9MQDaWZrfghUAJPmm9uJwCEyZzNZSzPVxs1WKbMXbn"); +declare_id!("3ESz1nYWmkdp9A3SByK7mbf9toDSRPvJADDF6pz45qZG"); #[program] pub mod wormhole_reporter { @@ -66,14 +66,113 @@ pub mod wormhole_reporter { // But for fun, we will store our emitter's bump for convenience. ctx.accounts.wormhole_emitter.bump = ctx.bumps.wormhole_emitter; - // Done. + { + // If Wormhole requires a fee before posting a message, we need to + // transfer lamports to the fee collector. Otherwise + // `wormhole::post_message` will fail. + let fee = ctx.accounts.wormhole_bridge.fee(); + if fee > 0 { + solana_program::program::invoke( + &solana_program::system_instruction::transfer( + &ctx.accounts.owner.key(), + &ctx.accounts.wormhole_fee_collector.key(), + fee, + ), + &ctx.accounts.to_account_infos(), + )?; + } + + // Invoke `wormhole::post_message`. We are sending a Wormhole + // message in the `initialize` instruction so the Wormhole program + // can create a SequenceTracker account for our emitter. We will + // deserialize this account for our `send_message` instruction so + // we can find the next sequence number. More details about this in + // `send_message`. + // + // `wormhole::post_message` requires two signers: one for the + // emitter and another for the wormhole message data. Both of these + // accounts are owned by this program. + // + // There are two ways to handle the wormhole message data account: + // 1. Using an extra keypair. You may to generate a keypair + // outside of this instruction and pass that keypair as an + // additional signer for the transaction. An integrator might + // use an extra keypair if the message can be "thrown away" + // (not easily retrievable without going back to this + // transaction hash to retrieve the message's pubkey). + // 2. Generate a PDA. If we want some way to deserialize the + // message data written by the Wormhole program, we can use an + // account with an address derived by this program so we can + // use the PDA to access and deserialize the message data. + // + // In our example, we use method #2. + let wormhole_emitter = &ctx.accounts.wormhole_emitter; + let config = &ctx.accounts.config; + + // If anyone were to care about the first message this program + // emits, he can deserialize it to find the program with which + // the emitter PDA was derived. + let payload = ctx.program_id.try_to_vec()?; + + wormhole::post_message( + CpiContext::new_with_signer( + ctx.accounts.wormhole_program.to_account_info(), + wormhole::PostMessage { + config: ctx.accounts.wormhole_bridge.to_account_info(), + message: ctx.accounts.wormhole_message.to_account_info(), + emitter: wormhole_emitter.to_account_info(), + sequence: ctx.accounts.wormhole_sequence.to_account_info(), + payer: ctx.accounts.owner.to_account_info(), + fee_collector: ctx.accounts.wormhole_fee_collector.to_account_info(), + clock: ctx.accounts.clock.to_account_info(), + rent: ctx.accounts.rent.to_account_info(), + system_program: ctx.accounts.system_program.to_account_info(), + }, + &[ + &[ + SEED_PREFIX_SENT, + &wormhole::INITIAL_SEQUENCE.to_le_bytes()[..], + &[ctx.bumps.wormhole_message], + ], + &[wormhole::SEED_PREFIX_EMITTER, &[wormhole_emitter.bump]], + ], + ), + config.batch_id, + payload, + config.finality.try_into().unwrap(), + )?; + } + Ok(()) } + /// Dispatches a Wormhole message for a specific slot. + /// + /// This function handles the necessary steps to post a message to the Wormhole bridge, + /// including paying the required fee (if any), preparing the message payload, and invoking + /// the `wormhole::post_message` CPI. It uses Program Derived Addresses (PDAs) to manage + /// the Wormhole emitter and message accounts securely and reliably. + /// + /// # Arguments + /// + /// - `ctx`: A `Context` object containing all necessary accounts and data required for the dispatch process. + /// - `slot_number`: The slot number for which the message is being dispatched. This is used to + /// retrieve the slot hash and include it in the payload. + /// + /// # Notes + /// + /// - The function uses a PDA to manage the Wormhole message account, allowing the program + /// to retain access to and deserialize the message data as needed. + /// - The Wormhole emitter and sequence accounts are derived and managed by this program. + /// - The finality of the message is determined by the configuration stored in the `config` account. + /// + /// # Returns + /// + /// This function returns `Ok(())` on success or a relevant error if the process fails. pub fn dispatch_slot( ctx: Context, - target_chain_id: [u8; 32], - receiver: Vec, + /*target_chain_id: [u8; 32], + receiver: Vec,*/ slot_number: u64, ) -> Result<()> { // If Wormhole requires a fee before posting a message, we need to @@ -115,7 +214,8 @@ pub mod wormhole_reporter { let slot_hash = get_slot(&ctx.accounts.slot_hashes, slot_number)?; let message = Message::from((slot_number, slot_hash)); - let payload = message.try_to_vec()?; + let mut payload: Vec = Vec::new(); + message.serialize(&mut payload)?; wormhole::post_message( CpiContext::new_with_signer( diff --git a/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs b/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs index 36007a7e..28729c0b 100644 --- a/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs +++ b/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs @@ -17,19 +17,3 @@ impl WormholeEmitter { /// [`SEED_PREFIX_EMITTER`](wormhole::SEED_PREFIX_EMITTER)). pub const SEED_PREFIX: &'static [u8; 7] = wormhole::SEED_PREFIX_EMITTER; } - -#[cfg(test)] -mod test { - use super::*; - use std::mem::size_of; - - #[test] - fn test_wormhole_emitter() -> Result<()> { - assert_eq!( - WormholeEmitter::MAXIMUM_SIZE, - size_of::() + size_of::() - ); - - Ok(()) - } -} diff --git a/packages/solana/shared/message/Cargo.toml b/packages/solana/shared/message/Cargo.toml index 90775306..f1b9d2b4 100644 --- a/packages/solana/shared/message/Cargo.toml +++ b/packages/solana/shared/message/Cargo.toml @@ -13,4 +13,6 @@ no-log-ix-name = [] idl-build = ["anchor-lang/idl-build"] [dependencies] +alloy-sol-types = "0.7.0" +alloy-primitives = "0.7.0" anchor-lang = "0.30.1" \ No newline at end of file diff --git a/packages/solana/shared/message/src/lib.rs b/packages/solana/shared/message/src/lib.rs index 9344d428..89692adf 100644 --- a/packages/solana/shared/message/src/lib.rs +++ b/packages/solana/shared/message/src/lib.rs @@ -1,26 +1,62 @@ -use anchor_lang::prelude::*; -use borsh::{BorshDeserialize, BorshSerialize}; +use alloy_primitives::U256; +use alloy_sol_types::{sol_data, SolType}; +use anchor_lang::AnchorSerialize; use std::convert::From; +use std::io; -#[derive(BorshDeserialize, BorshSerialize)] +/// A struct representing a message with associated IDs and hashes. pub struct Message { - pub ids: Vec<[u8; 32]>, + /// A vector of 256-bit unsigned integers representing IDs. + pub ids: Vec, + /// A vector of 32-byte arrays representing hashes. pub hashes: Vec<[u8; 32]>, } +/// Converts a tuple `(u64, [u8; 32])` into a `Message`. impl From<(u64, [u8; 32])> for Message { + /// Converts a `(u64, [u8; 32])` tuple into a `Message` by: + /// - Converting the `u64` into a `U256`. + /// - Adding the hash as a single entry in the `hashes` vector. + /// + /// # Arguments + /// + /// * `value` - A tuple containing: + /// - `u64`: The ID to be converted to a `U256`. + /// - `[u8; 32]`: The hash to be added to the `hashes` vector. + /// + /// # Returns + /// + /// A new `Message` instance with the given ID and hash. fn from(value: (u64, [u8; 32])) -> Self { let (id, hash) = value; Message { - ids: vec![u64_to_u8_32(id)], + ids: vec![U256::from(id)], hashes: vec![hash], } } } -fn u64_to_u8_32(number: u64) -> [u8; 32] { - let mut bytes = [0u8; 32]; - let number_bytes = number.to_be_bytes(); - bytes[24..].copy_from_slice(&number_bytes); - bytes +/// Provides serialization support for the `Message` struct using Anchor's serialization trait. +impl AnchorSerialize for Message { + /// Serializes the `Message` struct into a Solidity ABI-encoded format. + /// + /// The `ids` field is serialized as an array of 256-bit unsigned integers, + /// and the `hashes` field is serialized as an array of 32-byte fixed-length arrays. + /// + /// # Arguments + /// + /// * `writer` - A mutable reference to an object implementing `io::Write` where + /// the serialized data will be written. + /// + /// # Returns + /// + /// * `Ok(())` if the serialization succeeds. + fn serialize(&self, writer: &mut W) -> io::Result<()> { + let encoded = <( + sol_data::Array>, + sol_data::Array>, + )>::abi_encode_params(&(self.ids.clone(), self.hashes.clone())); + writer.write_all(&encoded)?; + Ok(()) + } } diff --git a/packages/solana/tests/wormhole-reporter.ts b/packages/solana/tests/wormhole-reporter.ts new file mode 100644 index 00000000..e1dd5220 --- /dev/null +++ b/packages/solana/tests/wormhole-reporter.ts @@ -0,0 +1,103 @@ +import * as anchor from "@coral-xyz/anchor" +import { expect } from "chai" +import { Keypair, LAMPORTS_PER_SOL, PublicKey, PublicKeyInitData, SYSVAR_SLOT_HASHES_PUBKEY } from "@solana/web3.js" +import { + deriveAddress, + getPostMessageCpiAccounts, + getWormholeDerivedAccounts, +} from "@certusone/wormhole-sdk/lib/cjs/solana" +import { getPostedMessage, getProgramSequenceTracker } from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole" +import { CONTRACTS } from "@certusone/wormhole-sdk" +import { Program } from "@coral-xyz/anchor" +import { AbiCoder } from "ethers" + +import { WormholeReporter } from "../target/types/wormhole_reporter" + +const WORMHOLE_CONTRACTS = CONTRACTS.MAINNET +const CORE_BRIDGE_PID = new PublicKey(WORMHOLE_CONTRACTS.solana.core) + +const deriveWormholeMessageKey = (_programId: PublicKeyInitData, _sequence: bigint) => { + return deriveAddress( + [ + Buffer.from("sent"), + (() => { + const buf = Buffer.alloc(8) + buf.writeBigUInt64LE(_sequence) + return buf + })(), + ], + _programId, + ) +} + +describe("wormhole_reporter", () => { + const provider = anchor.AnchorProvider.local() + anchor.setProvider(provider) + const payer = new Keypair() + const reporter = anchor.workspace.WormholeReporter as Program + + before(async () => { + await provider.connection.confirmTransaction( + await provider.connection.requestAirdrop(payer.publicKey, 1000 * LAMPORTS_PER_SOL), + ) + }) + + describe("initialize", () => { + it("should set up the program", async () => { + const message = deriveWormholeMessageKey(reporter.programId, 1n) + const wormholeAccounts = getPostMessageCpiAccounts(reporter.programId, CORE_BRIDGE_PID, payer.publicKey, message) + const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], reporter.programId) + + await reporter.methods + .initialize() + .accounts({ + owner: new PublicKey(payer.publicKey), + config: configKey, + wormholeProgram: new PublicKey(CORE_BRIDGE_PID), + ...wormholeAccounts, + }) + .signers([payer]) + .rpc() + + const configData = await reporter.account.config.fetch(configKey) + expect(configData.owner).deep.equals(payer.publicKey) + const { wormholeBridge, wormholeFeeCollector } = getWormholeDerivedAccounts(reporter.programId, CORE_BRIDGE_PID) + expect(configData.wormhole.bridge).deep.equals(wormholeBridge) + expect(configData.wormhole.feeCollector).deep.equals(wormholeFeeCollector) + }) + }) + + describe("dispatch_slot", () => { + it("should dispatch slot", async () => { + const slot = await provider.connection.getSlot() + const slotNumberToDispatch = new anchor.BN(slot - 1) + + const tracker = await getProgramSequenceTracker(provider.connection, reporter.programId, CORE_BRIDGE_PID) + const message = deriveWormholeMessageKey(reporter.programId, tracker.sequence + 1n) + const wormholeAccounts = getPostMessageCpiAccounts(reporter.programId, CORE_BRIDGE_PID, payer.publicKey, message) + + await reporter.methods + .dispatchSlot(slotNumberToDispatch) + .accounts({ + config: PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], reporter.programId), + wormholeProgram: new PublicKey(CORE_BRIDGE_PID), + slotHashes: SYSVAR_SLOT_HASHES_PUBKEY, + ...wormholeAccounts, + }) + .signers([payer]) + .rpc() + + const { payload } = ( + await getPostedMessage(provider.connection, deriveWormholeMessageKey(reporter.programId, tracker.value() + 1n)) + ).message + + const abiCoder = new AbiCoder() + const [[dispatchedSlotNumber], [dispatchedSlotHash]] = abiCoder.decode( + ["uint256[]", "bytes32[]"], + "0x" + payload.toString("hex"), + ) + expect(parseInt(dispatchedSlotNumber)).equals(slotNumberToDispatch.toNumber()) + expect(dispatchedSlotHash).to.be.not.null + }) + }) +}) diff --git a/packages/solana/tsconfig.json b/packages/solana/tsconfig.json index cd5d2e3d..308cf8a5 100644 --- a/packages/solana/tsconfig.json +++ b/packages/solana/tsconfig.json @@ -2,9 +2,11 @@ "compilerOptions": { "types": ["mocha", "chai"], "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], + "lib": ["es2020"], "module": "commonjs", - "target": "es6", + "target": "es2020", + "strict": true, + "resolveJsonModule": true, "esModuleInterop": true } } diff --git a/yarn.lock b/yarn.lock index 53391635..92f5eb51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,6 +12,26 @@ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== +"@apollo/client@^3.5.8": + version "3.11.10" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.11.10.tgz#e16ae82ea9b16536ffd109847d24f9293fab5c4d" + integrity sha512-IfGc+X4il0rDqVQBBWdxIKM+ciDCiDzBq9+Bg9z4tJMi87uF6po4v+ddiac1wP0ARgVPsFwEIGxK7jhN4pW8jg== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + "@wry/caches" "^1.0.0" + "@wry/equality" "^0.5.6" + "@wry/trie" "^0.5.0" + graphql-tag "^2.12.6" + hoist-non-react-statics "^3.3.2" + optimism "^0.18.0" + prop-types "^15.7.2" + rehackt "^0.1.0" + response-iterator "^0.2.6" + symbol-observable "^4.0.0" + ts-invariant "^0.10.3" + tslib "^2.3.0" + zen-observable-ts "^1.2.5" + "@aws-crypto/sha256-js@1.2.2": version "1.2.2" resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz#02acd1a1fda92896fc5a28ec7c6e164644ea32fc" @@ -73,6 +93,13 @@ js-tokens "^4.0.0" picocolors "^1.0.0" +"@babel/runtime@7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.25.0": version "7.25.6" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2" @@ -80,6 +107,51 @@ dependencies: regenerator-runtime "^0.14.0" +"@certusone/wormhole-sdk-proto-web@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@certusone/wormhole-sdk-proto-web/-/wormhole-sdk-proto-web-0.0.7.tgz#3b4ff42227eaabbd8c89a781df1856b476b03764" + integrity sha512-GCe1/bcqMS0Mt+hsWp4SE4NLL59pWmK0lhQXO0oqAKl0G9AuuTdudySMDF/sLc7z5H2w34bSuSrIEKvPuuSC+w== + dependencies: + "@improbable-eng/grpc-web" "^0.15.0" + protobufjs "^7.0.0" + rxjs "^7.5.6" + +"@certusone/wormhole-sdk-wasm@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@certusone/wormhole-sdk-wasm/-/wormhole-sdk-wasm-0.0.1.tgz#05f0c05acba3df5bd025eaa9c7a3d55e017a771f" + integrity sha512-LdIwLhOyr4pPs2jqYubqC7d4UkqYBX0EG/ppspQlW3qlVE0LZRMrH6oVzzLMyHtV0Rw7O9sIKzORW/T3mrJv2w== + dependencies: + "@types/long" "^4.0.2" + "@types/node" "^18.0.3" + +"@certusone/wormhole-sdk@^0.10.18": + version "0.10.18" + resolved "https://registry.yarnpkg.com/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.18.tgz#a300381b838108d3fc31be2056de976e718029a9" + integrity sha512-VuN4AGB018ELkzTT/jN+yWgE6TWqXsHilxxCVWqGctzow2hKSFd8ADUhxhHigies436rS0vPvrgXi6m0J1+Ecw== + dependencies: + "@certusone/wormhole-sdk-proto-web" "0.0.7" + "@certusone/wormhole-sdk-wasm" "^0.0.1" + "@coral-xyz/borsh" "0.2.6" + "@mysten/sui.js" "0.32.2" + "@project-serum/anchor" "^0.25.0" + "@solana/spl-token" "^0.3.5" + "@solana/web3.js" "^1.66.2" + "@terra-money/terra.js" "3.1.9" + "@xpla/xpla.js" "^0.2.1" + algosdk "^2.4.0" + aptos "1.5.0" + axios "^0.24.0" + bech32 "^2.0.0" + binary-parser "^2.2.1" + bs58 "^4.0.1" + elliptic "^6.5.4" + js-base64 "^3.6.1" + near-api-js "^1.0.0" + optionalDependencies: + "@injectivelabs/networks" "1.10.12" + "@injectivelabs/sdk-ts" "1.10.72" + "@injectivelabs/utils" "1.10.12" + "@chainlink/contracts-ccip@0.7.6": version "0.7.6" resolved "https://registry.yarnpkg.com/@chainlink/contracts-ccip/-/contracts-ccip-0.7.6.tgz#5bf4568a0bbf4e29d2e8c32348e5ecc6ced006d2" @@ -126,6 +198,16 @@ "@chainsafe/persistent-merkle-tree" "^0.4.2" case "^1.6.3" +"@classic-terra/terra.proto@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@classic-terra/terra.proto/-/terra.proto-1.1.0.tgz#e314d89f59b49e79a04db25f66f658e5e5aa1890" + integrity sha512-bYhQG5LUaGF0KPRY9hYT/HEcd1QExZPQd6zLV/rQkCe/eDxfwFRLzZHpaaAdfWoAAZjsRWqJbUCqCg7gXBbJpw== + dependencies: + "@improbable-eng/grpc-web" "^0.14.1" + google-protobuf "^3.17.3" + long "^4.0.0" + protobufjs "~6.11.2" + "@colors/colors@1.6.0", "@colors/colors@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" @@ -292,6 +374,14 @@ dependencies: chalk "^4.1.0" +"@confio/ics23@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@confio/ics23/-/ics23-0.6.8.tgz#2a6b4f1f2b7b20a35d9a0745bb5a446e72930b3d" + integrity sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w== + dependencies: + "@noble/hashes" "^1.0.0" + protobufjs "^6.8.8" + "@connext/interfaces@2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@connext/interfaces/-/interfaces-2.0.0.tgz#17f27a516315e40a440c3ef34db83834ad51917f" @@ -323,6 +413,14 @@ superstruct "^0.15.4" toml "^3.0.0" +"@coral-xyz/borsh@0.2.6": + version "0.2.6" + resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.2.6.tgz#0f11b223bf2967574310705afd3c53ce26688ada" + integrity sha512-y6nmHw1bFcJib7sMHsQPpC8r47xhqDZVvhUdna7NUPzpSbOZG6f46N21+aXsQ2w/tG8Ggls488J/ZmwbgVmyjg== + dependencies: + bn.js "^5.1.2" + buffer-layout "^1.2.0" + "@coral-xyz/borsh@^0.30.1": version "0.30.1" resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.30.1.tgz#869d8833abe65685c72e9199b8688477a4f6b0e3" @@ -331,6 +429,38 @@ bn.js "^5.1.2" buffer-layout "^1.2.0" +"@cosmjs/amino@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.30.1.tgz#7c18c14627361ba6c88e3495700ceea1f76baace" + integrity sha512-yNHnzmvAlkETDYIpeCTdVqgvrdt1qgkOXwuRVi8s27UKI5hfqyE9fJ/fuunXE6ZZPnKkjIecDznmuUOMrMvw4w== + dependencies: + "@cosmjs/crypto" "^0.30.1" + "@cosmjs/encoding" "^0.30.1" + "@cosmjs/math" "^0.30.1" + "@cosmjs/utils" "^0.30.1" + +"@cosmjs/crypto@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.30.1.tgz#21e94d5ca8f8ded16eee1389d2639cb5c43c3eb5" + integrity sha512-rAljUlake3MSXs9xAm87mu34GfBLN0h/1uPPV6jEwClWjNkAMotzjC0ab9MARy5FFAvYHL3lWb57bhkbt2GtzQ== + dependencies: + "@cosmjs/encoding" "^0.30.1" + "@cosmjs/math" "^0.30.1" + "@cosmjs/utils" "^0.30.1" + "@noble/hashes" "^1" + bn.js "^5.2.0" + elliptic "^6.5.4" + libsodium-wrappers "^0.7.6" + +"@cosmjs/encoding@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.30.1.tgz#b5c4e0ef7ceb1f2753688eb96400ed70f35c6058" + integrity sha512-rXmrTbgqwihORwJ3xYhIgQFfMSrwLu1s43RIK9I8EBudPx3KmnmyAKzMOVsRDo9edLFNuZ9GIvysUCwQfq3WlQ== + dependencies: + base64-js "^1.3.0" + bech32 "^1.1.4" + readonly-date "^1.0.0" + "@cosmjs/encoding@^0.31.3": version "0.31.3" resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.31.3.tgz#2519d9c9ae48368424971f253775c4580b54c5aa" @@ -340,6 +470,90 @@ bech32 "^1.1.4" readonly-date "^1.0.0" +"@cosmjs/json-rpc@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/json-rpc/-/json-rpc-0.30.1.tgz#16f21305fc167598c8a23a45549b85106b2372bc" + integrity sha512-pitfC/2YN9t+kXZCbNuyrZ6M8abnCC2n62m+JtU9vQUfaEtVsgy+1Fk4TRQ175+pIWSdBMFi2wT8FWVEE4RhxQ== + dependencies: + "@cosmjs/stream" "^0.30.1" + xstream "^11.14.0" + +"@cosmjs/math@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.30.1.tgz#8b816ef4de5d3afa66cb9fdfb5df2357a7845b8a" + integrity sha512-yaoeI23pin9ZiPHIisa6qqLngfnBR/25tSaWpkTm8Cy10MX70UF5oN4+/t1heLaM6SSmRrhk3psRkV4+7mH51Q== + dependencies: + bn.js "^5.2.0" + +"@cosmjs/proto-signing@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.30.1.tgz#f0dda372488df9cd2677150b89b3e9c72b3cb713" + integrity sha512-tXh8pPYXV4aiJVhTKHGyeZekjj+K9s2KKojMB93Gcob2DxUjfKapFYBMJSgfKPuWUPEmyr8Q9km2hplI38ILgQ== + dependencies: + "@cosmjs/amino" "^0.30.1" + "@cosmjs/crypto" "^0.30.1" + "@cosmjs/encoding" "^0.30.1" + "@cosmjs/math" "^0.30.1" + "@cosmjs/utils" "^0.30.1" + cosmjs-types "^0.7.1" + long "^4.0.0" + +"@cosmjs/socket@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/socket/-/socket-0.30.1.tgz#00b22f4b5e2ab01f4d82ccdb7b2e59536bfe5ce0" + integrity sha512-r6MpDL+9N+qOS/D5VaxnPaMJ3flwQ36G+vPvYJsXArj93BjgyFB7BwWwXCQDzZ+23cfChPUfhbINOenr8N2Kow== + dependencies: + "@cosmjs/stream" "^0.30.1" + isomorphic-ws "^4.0.1" + ws "^7" + xstream "^11.14.0" + +"@cosmjs/stargate@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.30.1.tgz#e1b22e1226cffc6e93914a410755f1f61057ba04" + integrity sha512-RdbYKZCGOH8gWebO7r6WvNnQMxHrNXInY/gPHPzMjbQF6UatA6fNM2G2tdgS5j5u7FTqlCI10stNXrknaNdzog== + dependencies: + "@confio/ics23" "^0.6.8" + "@cosmjs/amino" "^0.30.1" + "@cosmjs/encoding" "^0.30.1" + "@cosmjs/math" "^0.30.1" + "@cosmjs/proto-signing" "^0.30.1" + "@cosmjs/stream" "^0.30.1" + "@cosmjs/tendermint-rpc" "^0.30.1" + "@cosmjs/utils" "^0.30.1" + cosmjs-types "^0.7.1" + long "^4.0.0" + protobufjs "~6.11.3" + xstream "^11.14.0" + +"@cosmjs/stream@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/stream/-/stream-0.30.1.tgz#ba038a2aaf41343696b1e6e759d8e03a9516ec1a" + integrity sha512-Fg0pWz1zXQdoxQZpdHRMGvUH5RqS6tPv+j9Eh7Q953UjMlrwZVo0YFLC8OTf/HKVf10E4i0u6aM8D69Q6cNkgQ== + dependencies: + xstream "^11.14.0" + +"@cosmjs/tendermint-rpc@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.30.1.tgz#c16378892ba1ac63f72803fdf7567eab9d4f0aa0" + integrity sha512-Z3nCwhXSbPZJ++v85zHObeUggrEHVfm1u18ZRwXxFE9ZMl5mXTybnwYhczuYOl7KRskgwlB+rID0WYACxj4wdQ== + dependencies: + "@cosmjs/crypto" "^0.30.1" + "@cosmjs/encoding" "^0.30.1" + "@cosmjs/json-rpc" "^0.30.1" + "@cosmjs/math" "^0.30.1" + "@cosmjs/socket" "^0.30.1" + "@cosmjs/stream" "^0.30.1" + "@cosmjs/utils" "^0.30.1" + axios "^0.21.2" + readonly-date "^1.0.0" + xstream "^11.14.0" + +"@cosmjs/utils@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.30.1.tgz#6d92582341be3c2ec8d82090253cfa4b7f959edb" + integrity sha512-KvvX58MGMWh7xA+N+deCfunkA/ZNDvFLw4YbOmX3f/XBIkqrVY7qlotfy2aNb1kgp6h4B6Yc8YawJPDTfvWX7g== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -445,6 +659,14 @@ "@ethereumjs/util" "^9.1.0" ethereum-cryptography "^2.2.1" +"@ethereumjs/common@^2.6.4": + version "2.6.5" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" + integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.5" + "@ethereumjs/common@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-4.4.0.tgz#fba41612f527a815bf304e98653d6b5fc5d6d4de" @@ -475,6 +697,14 @@ lru-cache "10.1.0" readable-stream "^3.6.0" +"@ethereumjs/tx@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" + integrity sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw== + dependencies: + "@ethereumjs/common" "^2.6.4" + ethereumjs-util "^7.1.5" + "@ethereumjs/tx@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-5.4.0.tgz#6f47894cc3e2d4e63d87c62b41ed7e8180a1de58" @@ -576,7 +806,7 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.6.1", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== @@ -658,7 +888,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.6.1", "@ethersproject/keccak256@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== @@ -744,7 +974,7 @@ "@ethersproject/logger" "^5.7.0" hash.js "1.1.7" -"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.6.2", "@ethersproject/signing-key@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== @@ -849,6 +1079,11 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== +"@graphql-typed-document-node/core@^3.1.1": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@humanwhocodes/config-array@^0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" @@ -888,6 +1123,208 @@ bignumber.js "^9.1.1" ethers "^5.7.2" +"@improbable-eng/grpc-web@^0.14.1": + version "0.14.1" + resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz#f4662f64dc89c0f956a94bb8a3b576556c74589c" + integrity sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw== + dependencies: + browser-headers "^0.4.1" + +"@improbable-eng/grpc-web@^0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz#3e47e9fdd90381a74abd4b7d26e67422a2a04bef" + integrity sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg== + dependencies: + browser-headers "^0.4.1" + +"@injectivelabs/core-proto-ts@^0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@injectivelabs/core-proto-ts/-/core-proto-ts-0.0.14.tgz#88f3c3c5c88484906785cd93b2e2eb1d464ec5d4" + integrity sha512-NZWlgBzgVrXow9IknFQHvcYKX4QkUD25taRigoNYQK8PDn4+VXd9xM5WFUDRhzm2smTCguyl/+MghpEp4oTPWw== + dependencies: + "@injectivelabs/grpc-web" "^0.0.1" + google-protobuf "^3.14.0" + protobufjs "^7.0.0" + rxjs "^7.4.0" + +"@injectivelabs/exceptions@^1.10.12", "@injectivelabs/exceptions@^1.14.11", "@injectivelabs/exceptions@^1.14.33": + version "1.14.33" + resolved "https://registry.yarnpkg.com/@injectivelabs/exceptions/-/exceptions-1.14.33.tgz#3bcc3e613aac13fce72b3557b4260820dde8ce3a" + integrity sha512-2c8YzLgwTOOsyc1WheqdM8jEfgGBhVrXN4cZ0jsikFVsLF619IDRn3hjIYqTeNERaEpeRPiuJGfZDu0DomwFrQ== + dependencies: + "@injectivelabs/grpc-web" "^0.0.1" + "@injectivelabs/ts-types" "^1.14.33" + http-status-codes "^2.2.0" + shx "^0.3.2" + +"@injectivelabs/grpc-web-node-http-transport@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@injectivelabs/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.0.2.tgz#87c9bbd4db1f70cf18d6a55b54b2cf17d3cf30c0" + integrity sha512-rpyhXLiGY/UMs6v6YmgWHJHiO9l0AgDyVNv+jcutNVt4tQrmNvnpvz2wCAGOFtq5LuX/E9ChtTVpk3gWGqXcGA== + +"@injectivelabs/grpc-web-react-native-transport@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@injectivelabs/grpc-web-react-native-transport/-/grpc-web-react-native-transport-0.0.2.tgz#07601b76bf1f165c7a9b97ee42d0d42b9e2b76fa" + integrity sha512-mk+aukQXnYNgPsPnu3KBi+FD0ZHQpazIlaBZ2jNZG7QAVmxTWtv3R66Zoq99Wx2dnE946NsZBYAoa0K5oSjnow== + +"@injectivelabs/grpc-web@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@injectivelabs/grpc-web/-/grpc-web-0.0.1.tgz#24c028f6db50e589e30505efd2077110c8b492ba" + integrity sha512-Pu5YgaZp+OvR5UWfqbrPdHer3+gDf+b5fQoY+t2VZx1IAVHX8bzbN9EreYTvTYtFeDpYRWM8P7app2u4EX5wTw== + dependencies: + browser-headers "^0.4.1" + +"@injectivelabs/indexer-proto-ts@1.10.8-rc.4": + version "1.10.8-rc.4" + resolved "https://registry.yarnpkg.com/@injectivelabs/indexer-proto-ts/-/indexer-proto-ts-1.10.8-rc.4.tgz#ab8424cd713bb5a69ab130b64bf0b3f9f9089946" + integrity sha512-IwbepTfsHHAv3Z36As6yH/+HIplOEpUu6SFHBCVgdSIaQ8GuvTib4HETiVnV4mjYqoyVgWs+zLSAfih46rdMJQ== + dependencies: + "@injectivelabs/grpc-web" "^0.0.1" + google-protobuf "^3.14.0" + protobufjs "^7.0.0" + rxjs "^7.4.0" + +"@injectivelabs/mito-proto-ts@1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@injectivelabs/mito-proto-ts/-/mito-proto-ts-1.0.9.tgz#ad04165ad63f52a9f67082318e0620cccc4986f2" + integrity sha512-+TZMvJ4SHwcn6SFPdqaiQFZdNhjH7hyRFozY15nOTC2utdGij9jEsjz1NsyOejfYDA0s1z5Wm1SgrMYKaVpAmQ== + dependencies: + "@injectivelabs/grpc-web" "^0.0.1" + google-protobuf "^3.14.0" + protobufjs "^7.0.0" + rxjs "^7.4.0" + +"@injectivelabs/networks@1.10.12": + version "1.10.12" + resolved "https://registry.yarnpkg.com/@injectivelabs/networks/-/networks-1.10.12.tgz#8c3fcf96a8930c28dcd44d779e1ef31e68ec7b0b" + integrity sha512-tTHyLls1Nik5QTs/S03qqG2y/ITvNwI8CJOQbMmmsr1CL2CdjJBtzRYn9Dyx2p8XgzRFf9hmlybpe20tq9O3SA== + dependencies: + "@injectivelabs/exceptions" "^1.10.12" + "@injectivelabs/ts-types" "^1.10.12" + "@injectivelabs/utils" "^1.10.12" + link-module-alias "^1.2.0" + shx "^0.3.2" + +"@injectivelabs/networks@^1.10.12", "@injectivelabs/networks@^1.14.11", "@injectivelabs/networks@^1.14.33": + version "1.14.33" + resolved "https://registry.yarnpkg.com/@injectivelabs/networks/-/networks-1.14.33.tgz#340bef9948ace5abd7b9a2a69ef1d9bc6ee54c33" + integrity sha512-XDhAYwWYKdKBRfwO/MIfMyKjKRWz/AliMJG9yaM1C/cDlGHmA3EY7Au2Nf+PdkRhuxl2FzLV2Hp4uWeC0g8BYw== + dependencies: + "@injectivelabs/exceptions" "^1.14.33" + "@injectivelabs/ts-types" "^1.14.33" + "@injectivelabs/utils" "^1.14.33" + shx "^0.3.2" + +"@injectivelabs/sdk-ts@1.10.72": + version "1.10.72" + resolved "https://registry.yarnpkg.com/@injectivelabs/sdk-ts/-/sdk-ts-1.10.72.tgz#07920960ef74aa9db96978a85d86042037836a51" + integrity sha512-A5mHNNBgO4fI1c/7CZ0bGfVXliy8laP+VaYZ++aWh1YyudoZw4CTCEmLetZRy7AUU3XcfbHa8sAImRi7db+v6Q== + dependencies: + "@apollo/client" "^3.5.8" + "@cosmjs/amino" "^0.30.1" + "@cosmjs/proto-signing" "^0.30.1" + "@cosmjs/stargate" "^0.30.1" + "@ethersproject/bytes" "^5.7.0" + "@injectivelabs/core-proto-ts" "^0.0.14" + "@injectivelabs/exceptions" "^1.10.12" + "@injectivelabs/grpc-web" "^0.0.1" + "@injectivelabs/grpc-web-node-http-transport" "^0.0.2" + "@injectivelabs/grpc-web-react-native-transport" "^0.0.2" + "@injectivelabs/indexer-proto-ts" "1.10.8-rc.4" + "@injectivelabs/mito-proto-ts" "1.0.9" + "@injectivelabs/networks" "^1.10.12" + "@injectivelabs/test-utils" "^1.10.12" + "@injectivelabs/token-metadata" "^1.10.42" + "@injectivelabs/ts-types" "^1.10.12" + "@injectivelabs/utils" "^1.10.12" + "@metamask/eth-sig-util" "^4.0.0" + axios "^0.27.2" + bech32 "^2.0.0" + bip39 "^3.0.4" + cosmjs-types "^0.7.1" + eth-crypto "^2.6.0" + ethereumjs-util "^7.1.4" + ethers "^5.7.2" + google-protobuf "^3.21.0" + graphql "^16.3.0" + http-status-codes "^2.2.0" + js-sha3 "^0.8.0" + jscrypto "^1.0.3" + keccak256 "^1.0.6" + link-module-alias "^1.2.0" + rxjs "^7.8.0" + secp256k1 "^4.0.3" + shx "^0.3.2" + snakecase-keys "^5.4.1" + +"@injectivelabs/test-utils@^1.10.12": + version "1.14.33" + resolved "https://registry.yarnpkg.com/@injectivelabs/test-utils/-/test-utils-1.14.33.tgz#2c800231f3b6179c808d8fff63cb9b2e87d462bc" + integrity sha512-1SfIRsMnWcJAYNrrpY+ZUWmbD62lWWdIvD6c+FYmFKS14zU3yDIK9NXe9g1lTM/GdUVkVKQgGg2QAYZ5f2G/xA== + dependencies: + "@injectivelabs/exceptions" "^1.14.33" + "@injectivelabs/networks" "^1.14.33" + "@injectivelabs/ts-types" "^1.14.33" + "@injectivelabs/utils" "^1.14.33" + axios "^1.6.4" + bignumber.js "^9.0.1" + shx "^0.3.2" + snakecase-keys "^5.1.2" + store2 "^2.12.0" + +"@injectivelabs/token-metadata@^1.10.42": + version "1.14.11" + resolved "https://registry.yarnpkg.com/@injectivelabs/token-metadata/-/token-metadata-1.14.11.tgz#296b6db3c9c9f6147273252cf41b803902c35414" + integrity sha512-WKJlvjKiTRHxpOeez4kYrzIwgWmpspD1IMxWclkTysAcwGltUfUsvUhu1cKuACleIjFFWmiZv/HoGRFdvEAZ8w== + dependencies: + "@injectivelabs/exceptions" "^1.14.11" + "@injectivelabs/networks" "^1.14.11" + "@injectivelabs/ts-types" "^1.14.11" + "@injectivelabs/utils" "^1.14.11" + "@types/lodash.values" "^4.3.6" + copyfiles "^2.4.1" + jsonschema "^1.4.0" + link-module-alias "^1.2.0" + lodash "^4.17.21" + lodash.values "^4.3.0" + shx "^0.3.2" + +"@injectivelabs/ts-types@^1.10.12", "@injectivelabs/ts-types@^1.14.11", "@injectivelabs/ts-types@^1.14.33": + version "1.14.33" + resolved "https://registry.yarnpkg.com/@injectivelabs/ts-types/-/ts-types-1.14.33.tgz#c06da4757a07f2140d01a4f4b0087c6053e8e58f" + integrity sha512-sJZzMNJtZFFZoPKZ91G09bxrZqQ5aS9omoTjQWy+7OxfiRAakzhsarTueX47hm6oTaN0XeBgD3wkMukkWUaobw== + dependencies: + shx "^0.3.2" + +"@injectivelabs/utils@1.10.12": + version "1.10.12" + resolved "https://registry.yarnpkg.com/@injectivelabs/utils/-/utils-1.10.12.tgz#063835b25c11182945881e82a2cbad50f6ca10b3" + integrity sha512-c8al79nxIJgV1cBAdW2TPDGldj/8gm5k0h5TIN/AJs8/AeIjpTwwVGfLY3QvPOpRsxuQ9CjBkTXrAcSL1wwkcw== + dependencies: + "@injectivelabs/exceptions" "^1.10.12" + "@injectivelabs/ts-types" "^1.10.12" + axios "^0.21.1" + bignumber.js "^9.0.1" + http-status-codes "^2.2.0" + link-module-alias "^1.2.0" + shx "^0.3.2" + snakecase-keys "^5.1.2" + store2 "^2.12.0" + +"@injectivelabs/utils@^1.10.12", "@injectivelabs/utils@^1.14.11", "@injectivelabs/utils@^1.14.33": + version "1.14.33" + resolved "https://registry.yarnpkg.com/@injectivelabs/utils/-/utils-1.14.33.tgz#9e6eef0e61f306ef5cd68ceed198ea98c47ada4e" + integrity sha512-zsezML4dTujF0xGLhcGmWBCghfJiy9MW+r6VqR8zJUlxnmnEdNpmsvBhBI6cmmov6Se4FL+yALAIFRvTm3txbg== + dependencies: + "@injectivelabs/exceptions" "^1.14.33" + "@injectivelabs/ts-types" "^1.14.33" + axios "^1.6.4" + bignumber.js "^9.0.1" + http-status-codes "^2.2.0" + shx "^0.3.2" + snakecase-keys "^5.1.2" + store2 "^2.12.0" + "@jridgewell/resolve-uri@^3.0.3": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" @@ -939,6 +1376,29 @@ dependencies: sparse-bitfield "^3.0.3" +"@mysten/bcs@0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@mysten/bcs/-/bcs-0.7.1.tgz#e8db25718143e2a15688ea858470970b743f7248" + integrity sha512-wFPb8bkhwrbiStfZMV5rFM7J+umpke59/dNjDp+UYJKykNlW23LCk2ePyEUvGdb62HGJM1jyOJ8g4egE3OmdKA== + dependencies: + bs58 "^5.0.0" + +"@mysten/sui.js@0.32.2": + version "0.32.2" + resolved "https://registry.yarnpkg.com/@mysten/sui.js/-/sui.js-0.32.2.tgz#dff953a336c787465af181d8158f34a65700a74f" + integrity sha512-/Hm4xkGolJhqj8FvQr7QSHDTlxIvL52mtbOao9f75YjrBh7y1Uh9kbJSY7xiTF1NY9sv6p5hUVlYRJuM0Hvn9A== + dependencies: + "@mysten/bcs" "0.7.1" + "@noble/curves" "^1.0.0" + "@noble/hashes" "^1.3.0" + "@scure/bip32" "^1.3.0" + "@scure/bip39" "^1.2.0" + "@suchipi/femver" "^1.0.0" + jayson "^4.0.0" + rpc-websockets "^7.5.1" + superstruct "^1.0.3" + tweetnacl "^1.0.3" + "@noble/curves@1.2.0", "@noble/curves@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" @@ -960,6 +1420,13 @@ dependencies: "@noble/hashes" "1.4.0" +"@noble/curves@^1.0.0", "@noble/curves@~1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== + dependencies: + "@noble/hashes" "1.6.0" + "@noble/curves@^1.4.0", "@noble/curves@^1.4.2": version "1.6.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b" @@ -967,6 +1434,11 @@ dependencies: "@noble/hashes" "1.5.0" +"@noble/hashes@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.3.tgz#360afc77610e0a61f3417e497dcf36862e4f8111" + integrity sha512-CE0FCR57H2acVI5UOzIGSSIYxZ6v/HOhDR0Ro9VLyhnzLwx0o8W1mmgaqlEUx4049qJDlIBRztv5k+MM8vbO3A== + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" @@ -987,11 +1459,21 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== -"@noble/hashes@^1.3.1": +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== + +"@noble/hashes@^1", "@noble/hashes@^1.0.0", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.0", "@noble/hashes@^1.3.1", "@noble/hashes@~1.6.0": version "1.6.1" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== +"@noble/hashes@~1.1.1": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" + integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== + "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": version "1.3.3" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" @@ -1430,6 +1912,88 @@ prettier "^3.3.3" prettier-plugin-solidity "^1.4.1" +"@project-serum/anchor@^0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.25.0.tgz#88ee4843336005cf5a64c80636ce626f0996f503" + integrity sha512-E6A5Y/ijqpfMJ5psJvbw0kVTzLZFUcOFgs6eSM2M2iWE1lVRF18T6hWZVNl6zqZsoz98jgnNHtVGJMs+ds9A7A== + dependencies: + "@project-serum/borsh" "^0.2.5" + "@solana/web3.js" "^1.36.0" + base64-js "^1.5.1" + bn.js "^5.1.2" + bs58 "^4.0.1" + buffer-layout "^1.2.2" + camelcase "^5.3.1" + cross-fetch "^3.1.5" + crypto-hash "^1.3.0" + eventemitter3 "^4.0.7" + js-sha256 "^0.9.0" + pako "^2.0.3" + snake-case "^3.0.4" + superstruct "^0.15.4" + toml "^3.0.0" + +"@project-serum/borsh@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.5.tgz#6059287aa624ecebbfc0edd35e4c28ff987d8663" + integrity sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q== + dependencies: + bn.js "^5.1.2" + buffer-layout "^1.2.0" + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + "@routerprotocol/evm-gateway-contracts@1.1.13": version "1.1.13" resolved "https://registry.yarnpkg.com/@routerprotocol/evm-gateway-contracts/-/evm-gateway-contracts-1.1.13.tgz#609cd2a0cbcdb92e9a55fcdcb5cba0cc62fc11a7" @@ -1443,6 +2007,11 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== +"@scure/base@~1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865" + integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ== + "@scure/bip32@1.1.5": version "1.1.5" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" @@ -1470,6 +2039,23 @@ "@noble/hashes" "~1.4.0" "@scure/base" "~1.1.6" +"@scure/bip32@^1.3.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891" + integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA== + dependencies: + "@noble/curves" "~1.7.0" + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + +"@scure/bip39@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" + integrity sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w== + dependencies: + "@noble/hashes" "~1.1.1" + "@scure/base" "~1.1.0" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -1502,6 +2088,14 @@ "@noble/hashes" "~1.5.0" "@scure/base" "~1.1.8" +"@scure/bip39@^1.2.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be" + integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A== + dependencies: + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -1577,14 +2171,104 @@ dependencies: tslib "^2.6.2" -"@solana/buffer-layout@^4.0.1": +"@solana/buffer-layout-utils@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca" + integrity sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/web3.js" "^1.32.0" + bigint-buffer "^1.1.5" + bignumber.js "^9.0.1" + +"@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== dependencies: buffer "~6.0.3" -"@solana/web3.js@^1.68.0": +"@solana/codecs-core@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz#1a2d76b9c7b9e7b7aeb3bd78be81c2ba21e3ce22" + integrity sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ== + dependencies: + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-data-structures@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-rc.1.tgz#d47b2363d99fb3d643f5677c97d64a812982b888" + integrity sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-numbers@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-rc.1.tgz#f34978ddf7ea4016af3aaed5f7577c1d9869a614" + integrity sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-strings@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-2.0.0-rc.1.tgz#e1d9167075b8c5b0b60849f8add69c0f24307018" + integrity sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs/-/codecs-2.0.0-rc.1.tgz#146dc5db58bd3c28e04b4c805e6096c2d2a0a875" + integrity sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-data-structures" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/codecs-strings" "2.0.0-rc.1" + "@solana/options" "2.0.0-rc.1" + +"@solana/errors@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.0.0-rc.1.tgz#3882120886eab98a37a595b85f81558861b29d62" + integrity sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ== + dependencies: + chalk "^5.3.0" + commander "^12.1.0" + +"@solana/options@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/options/-/options-2.0.0-rc.1.tgz#06924ba316dc85791fc46726a51403144a85fc4d" + integrity sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-data-structures" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/codecs-strings" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/spl-token-metadata@^0.1.2": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@solana/spl-token-metadata/-/spl-token-metadata-0.1.6.tgz#d240947aed6e7318d637238022a7b0981b32ae80" + integrity sha512-7sMt1rsm/zQOQcUWllQX9mD2O6KhSAtY1hFR2hfFwgqfFWzSY9E9GDvFVNYUI1F0iQKcm6HmePU9QbKRXTEBiA== + dependencies: + "@solana/codecs" "2.0.0-rc.1" + +"@solana/spl-token@^0.3.5": + version "0.3.11" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" + integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" + "@solana/spl-token-metadata" "^0.1.2" + buffer "^6.0.3" + +"@solana/web3.js@^1.32.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.66.2", "@solana/web3.js@^1.68.0": version "1.95.5" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.95.5.tgz#ba70da4c205c64249ed94369fe2d617c0347cd85" integrity sha512-hU9cBrbg1z6gEjLH9vwIckGBVB78Ijm0iZFNk4ocm5OD82piPwuk3MeQ1rfiKD9YQtr95krrcaopb49EmQJlRg== @@ -1645,6 +2329,11 @@ resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.18.0.tgz#8e77a02a09ecce957255a2f48c9a7178ec191908" integrity sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA== +"@suchipi/femver@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@suchipi/femver/-/femver-1.0.0.tgz#4909dcc069695e07bd23a64c4bfe411d11d9692f" + integrity sha512-bprE8+K5V+DPX7q2e2K57ImqNBdfGHDIWaGI5xHxZoxbKOuQZn4wzPiUxOAHnsUr3w3xHrWXwN7gnG/iIuEMIg== + "@swc/helpers@^0.5.11": version "0.5.13" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.13.tgz#33e63ff3cd0cade557672bd7888a39ce7d115a8c" @@ -1652,6 +2341,45 @@ dependencies: tslib "^2.4.0" +"@terra-money/legacy.proto@npm:@terra-money/terra.proto@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz#59c18f30da10d43200bab3ba8feb5b17e43a365f" + integrity sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ== + dependencies: + google-protobuf "^3.17.3" + long "^4.0.0" + protobufjs "~6.11.2" + +"@terra-money/terra.js@3.1.9": + version "3.1.9" + resolved "https://registry.yarnpkg.com/@terra-money/terra.js/-/terra.js-3.1.9.tgz#2d78f241902238ba0613a089c56c334eb1351c68" + integrity sha512-JulSvOHLM56fL7s+cIjIbZeWPBluq883X1soWxA4TG5rKkDythT/DHeLXr3jP5Ld/26VENPSg6lNvK7cEYKpiw== + dependencies: + "@classic-terra/terra.proto" "^1.1.0" + "@terra-money/terra.proto" "^2.1.0" + axios "^0.27.2" + bech32 "^2.0.0" + bip32 "^2.0.6" + bip39 "^3.0.3" + bufferutil "^4.0.3" + decimal.js "^10.2.1" + jscrypto "^1.0.1" + readable-stream "^3.6.0" + secp256k1 "^4.0.2" + tmp "^0.2.1" + utf-8-validate "^5.0.5" + ws "^7.5.9" + +"@terra-money/terra.proto@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@terra-money/terra.proto/-/terra.proto-2.1.0.tgz#5a2ed85fc8146a346d6095adfc5d205b6fb6d387" + integrity sha512-rhaMslv3Rkr+QsTQEZs64FKA4QlfO0DfQHaR6yct/EovenMkibDEQ63dEL6yJA6LCaEQGYhyVB9JO9pTUA8ybw== + dependencies: + "@improbable-eng/grpc-web" "^0.14.1" + google-protobuf "^3.17.3" + long "^4.0.0" + protobufjs "~6.11.2" + "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" @@ -1692,6 +2420,13 @@ dependencies: fs-extra "^9.1.0" +"@types/bn.js@5.1.6", "@types/bn.js@^5.1.0": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.6.tgz#9ba818eec0c85e4d3c679518428afdf611d03203" + integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== + dependencies: + "@types/node" "*" + "@types/bn.js@^4.11.3": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" @@ -1699,13 +2434,6 @@ dependencies: "@types/node" "*" -"@types/bn.js@^5.1.0": - version "5.1.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.6.tgz#9ba818eec0c85e4d3c679518428afdf611d03203" - integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== - dependencies: - "@types/node" "*" - "@types/body-parser@*": version "1.19.5" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" @@ -1795,6 +2523,23 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/lodash.values@^4.3.6": + version "4.3.9" + resolved "https://registry.yarnpkg.com/@types/lodash.values/-/lodash.values-4.3.9.tgz#a30e7d7cb715b1a01726838844da1dfbca549c2e" + integrity sha512-IJ20OEfqNwm3k8ENwoM3q0yOs4UMpgtD4GqxB4lwBHToGthHWqhyh5DdSgQjioocz0QK2SSBkJfCq95ZTV8BTw== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.13.tgz#786e2d67cfd95e32862143abe7463a7f90c300eb" + integrity sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg== + +"@types/long@^4.0.1", "@types/long@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + "@types/lru-cache@^5.1.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" @@ -1844,6 +2589,11 @@ dependencies: undici-types "~6.19.2" +"@types/node@10.12.18": + version "10.12.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" + integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== + "@types/node@18.15.13": version "18.15.13" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" @@ -1854,6 +2604,20 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.1.tgz#178d58ee7e4834152b0e8b4d30cbfab578b9bb30" integrity sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg== +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +"@types/node@>=13.7.0": + version "22.10.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.1.tgz#41ffeee127b8975a05f8c4f83fb89bcb2987d766" + integrity sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ== + dependencies: + undici-types "~6.20.0" + "@types/node@^10.0.3": version "10.17.60" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" @@ -1864,6 +2628,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== +"@types/node@^18.0.3": + version "18.19.67" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.67.tgz#77c4b01641a1e3e1509aff7e10d39e4afd5ae06d" + integrity sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ== + dependencies: + undici-types "~5.26.4" + "@types/node@^18.11.9": version "18.19.50" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.50.tgz#8652b34ee7c0e7e2004b3f08192281808d41bf5a" @@ -2190,6 +2961,60 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@wry/caches@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@wry/caches/-/caches-1.0.1.tgz#8641fd3b6e09230b86ce8b93558d44cf1ece7e52" + integrity sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA== + dependencies: + tslib "^2.3.0" + +"@wry/context@^0.7.0": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.7.4.tgz#e32d750fa075955c4ab2cfb8c48095e1d42d5990" + integrity sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ== + dependencies: + tslib "^2.3.0" + +"@wry/equality@^0.5.6": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.7.tgz#72ec1a73760943d439d56b7b1e9985aec5d497bb" + integrity sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.5.0.tgz#11e783f3a53f6e4cd1d42d2d1323f5bc3fa99c94" + integrity sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA== + dependencies: + tslib "^2.3.0" + +"@xpla/xpla.js@^0.2.1": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@xpla/xpla.js/-/xpla.js-0.2.3.tgz#c614d98e599fe03f9edc425f50f66481983e8dac" + integrity sha512-Tfk7hCGWXtwr08reY3Pi6dmzIqFbzri9jcyzJdfNmdo4cN0PMwpRJuZZcPmtxiIUnNef3AN1E/6nJUD5MKniuA== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/keccak256" "^5.6.1" + "@ethersproject/signing-key" "^5.6.2" + "@terra-money/legacy.proto" "npm:@terra-money/terra.proto@^0.1.7" + "@terra-money/terra.proto" "^2.1.0" + axios "^0.26.1" + bech32 "^2.0.0" + bip32 "^2.0.6" + bip39 "^3.0.3" + bufferutil "^4.0.3" + crypto-addr-codec "^0.1.7" + decimal.js "^10.2.1" + elliptic "^6.5.4" + ethereumjs-util "^7.1.5" + jscrypto "^1.0.1" + readable-stream "^3.6.0" + secp256k1 "^4.0.2" + tmp "^0.2.1" + utf-8-validate "^5.0.5" + ws "^7.5.8" + "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" @@ -2256,6 +3081,11 @@ acorn-walk@^8.1.1: dependencies: acorn "^8.11.0" +acorn@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" + integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== + acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: version "8.12.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" @@ -2318,6 +3148,26 @@ ajv@^8.0.1, ajv@^8.11.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" +algo-msgpack-with-bigint@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/algo-msgpack-with-bigint/-/algo-msgpack-with-bigint-2.1.1.tgz#38bb717220525b3ff42232eefdcd9efb9ad405d6" + integrity sha512-F1tGh056XczEaEAqu7s+hlZUDWwOBT70Eq0lfMpBP2YguSQVyxRbprLq5rELXKQOyOaixTWYhMeMQMzP0U5FoQ== + +algosdk@^2.4.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/algosdk/-/algosdk-2.9.0.tgz#a93cc26675e5310667ce5e9667305ce48a1818f9" + integrity sha512-o0n0nLMbTX6SFQdMUk2/2sy50jmEmZk5OTPYSh2aAeP8DUPxrhjMPfwGsYNvaO+qk75MixC2eWpfA9vygCQ/Mg== + dependencies: + algo-msgpack-with-bigint "^2.1.1" + buffer "^6.0.3" + hi-base32 "^0.5.1" + js-sha256 "^0.9.0" + js-sha3 "^0.8.0" + js-sha512 "^0.8.0" + json-bigint "^1.0.0" + tweetnacl "^1.0.3" + vlq "^2.0.4" + amazon-cognito-identity-js@^6.0.1: version "6.3.12" resolved "https://registry.yarnpkg.com/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.12.tgz#af73df033094ad4c679c19cf6122b90058021619" @@ -2393,6 +3243,17 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +aptos@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/aptos/-/aptos-1.5.0.tgz#43263b13c878d2497d875d50aaee10355932c2e6" + integrity sha512-N7OuRtU7IYHkDkNx+4QS3g/QQGCp+36KzYn3oXPmT7Kttfuv+UKliQVdjy3cLmwd/DCQSh9ObTovwdxnHjUn0g== + dependencies: + "@noble/hashes" "1.1.3" + "@scure/bip39" "1.1.0" + axios "0.27.2" + form-data "4.0.0" + tweetnacl "1.0.3" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -2499,6 +3360,14 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== +axios@0.27.2, axios@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + axios@^0.21.1, axios@^0.21.2: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" @@ -2506,6 +3375,20 @@ axios@^0.21.1, axios@^0.21.2: dependencies: follow-redirects "^1.14.0" +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + +axios@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== + dependencies: + follow-redirects "^1.14.8" + axios@^1.4.0, axios@^1.5.1: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" @@ -2515,19 +3398,33 @@ axios@^1.4.0, axios@^1.5.1: form-data "^4.0.0" proxy-from-env "^1.1.0" +axios@^1.6.4: + version "1.7.8" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.8.tgz#1997b1496b394c21953e68c14aaa51b7b5de3d6e" + integrity sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.2: +base-x@^3.0.2, base-x@^3.0.8: version "3.0.10" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== dependencies: safe-buffer "^5.0.1" -base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1: +base-x@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" + integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== + +base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2537,6 +3434,16 @@ bech32@1.1.4, bech32@^1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== +bech32@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" + integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== + +big-integer@1.6.36: + version "1.6.36" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36" + integrity sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg== + bigint-buffer@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/bigint-buffer/-/bigint-buffer-1.1.5.tgz#d038f31c8e4534c1f8d0015209bf34b4fa6dd442" @@ -2549,7 +3456,7 @@ bigint-crypto-utils@^3.0.23: resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz#72ad00ae91062cf07f2b1def9594006c279c1d77" integrity sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg== -bignumber.js@^9.1.1: +bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.1.1: version "9.1.2" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== @@ -2559,13 +3466,45 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -bindings@^1.3.0: +binary-parser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/binary-parser/-/binary-parser-2.2.1.tgz#4edc6da2dc56db73fa5ba450dfe6382ede8294ce" + integrity sha512-5ATpz/uPDgq5GgEDxTB4ouXCde7q2lqAQlSdBRQVl/AJnxmQmhIfyxJx+0MGu//D5rHQifkfGbWWlaysG0o9NA== + +bindings@^1.3.0, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" +bip32@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/bip32/-/bip32-2.0.6.tgz#6a81d9f98c4cd57d05150c60d8f9e75121635134" + integrity sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA== + dependencies: + "@types/node" "10.12.18" + bs58check "^2.1.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + tiny-secp256k1 "^1.1.3" + typeforce "^1.11.5" + wif "^2.0.6" + +bip39@^3.0.3, bip39@^3.0.4: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.1.0.tgz#c55a418deaf48826a6ceb34ac55b3ee1577e18a3" + integrity sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A== + dependencies: + "@noble/hashes" "^1.2.0" + +bip66@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" + integrity sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw== + dependencies: + safe-buffer "^5.0.1" + blakejs@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" @@ -2576,16 +3515,16 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== +bn.js@5.2.1, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - body-parser@1.20.3, body-parser@^1.20.2: version "1.20.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" @@ -2640,6 +3579,11 @@ brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== +browser-headers@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02" + integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg== + browser-level@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" @@ -2655,7 +3599,7 @@ browser-stdout@1.3.1, browser-stdout@^1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserify-aes@^1.2.0: +browserify-aes@^1.0.6, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -2674,7 +3618,14 @@ bs58@^4.0.0, bs58@^4.0.1: dependencies: base-x "^3.0.2" -bs58check@^2.1.2: +bs58@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" + integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== + dependencies: + base-x "^4.0.0" + +bs58check@<3.0.0, bs58check@^2.1.1, bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== @@ -2720,7 +3671,7 @@ buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -bufferutil@^4.0.1: +bufferutil@^4.0.1, bufferutil@^4.0.3: version "4.0.8" resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.8.tgz#1de6a71092d65d7766c4d8a522b261a6e787e8ea" integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw== @@ -2772,6 +3723,11 @@ camelcase@^6.0.0, camelcase@^6.3.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== +capability@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/capability/-/capability-0.2.5.tgz#51ad87353f1936ffd77f2f21c74633a4dea88801" + integrity sha512-rsJZYVCgXd08sPqwmaIqjAd5SUTfonV0z/gDJ8D6cN8wQphky1kkAYEqQ+hmDxTw7UihvBfjUVUSY+DBEe44jg== + case@^1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" @@ -2838,6 +3794,11 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + "charenc@>= 0.0.1": version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -3037,6 +3998,11 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -3121,6 +4087,19 @@ cookie@^0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== +copyfiles@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.4.1.tgz#d2dcff60aaad1015f09d0b66e7f0f1c5cd3c5da5" + integrity sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg== + dependencies: + glob "^7.0.5" + minimatch "^3.0.3" + mkdirp "^1.0.4" + noms "0.0.0" + through2 "^2.0.1" + untildify "^4.0.0" + yargs "^16.1.0" + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -3141,6 +4120,14 @@ cosmiconfig@^8.0.0: parse-json "^5.2.0" path-type "^4.0.0" +cosmjs-types@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.7.2.tgz#a757371abd340949c5bd5d49c6f8379ae1ffd7e2" + integrity sha512-vf2uLyktjr/XVAgEq0DjMxeAWh1yYREe7AMHDKd7EiHVqxBPCaBS+qEEQUkXbR9ndnckqr1sUG8BQhazh4X5lA== + dependencies: + long "^4.0.0" + protobufjs "~6.11.2" + crc-32@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" @@ -3195,6 +4182,19 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== +crypto-addr-codec@^0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/crypto-addr-codec/-/crypto-addr-codec-0.1.8.tgz#45c4b24e2ebce8e24a54536ee0ca25b65787b016" + integrity sha512-GqAK90iLLgP3FvhNmHbpT3wR6dEdaM8hZyZtLX29SPardh3OA13RFLHDR6sntGCgRWOfiHqW6sIyohpNqOtV/g== + dependencies: + base-x "^3.0.8" + big-integer "1.6.36" + blakejs "^1.1.0" + bs58 "^4.0.1" + ripemd160-min "0.0.6" + safe-buffer "^5.2.0" + sha3 "^2.1.1" + crypto-hash@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247" @@ -3249,6 +4249,11 @@ decamelize@^4.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +decimal.js@^10.2.1: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + deep-eql@^4.0.1, deep-eql@^4.1.3: version "4.1.4" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" @@ -3266,7 +4271,7 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -define-data-property@^1.1.4: +define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== @@ -3275,6 +4280,15 @@ define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" +define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + delay@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" @@ -3285,11 +4299,16 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -depd@2.0.0: +depd@2.0.0, depd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -3356,10 +4375,31 @@ dotenv@^16.0.3, dotenv@^16.3.1, dotenv@^16.4.5: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== +drbg.js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" + integrity sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g== + dependencies: + browserify-aes "^1.0.6" + create-hash "^1.1.2" + create-hmac "^1.1.4" + "ds-test@github:dapphub/ds-test": version "1.0.0" resolved "https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0" +eccrypto@1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/eccrypto/-/eccrypto-1.1.6.tgz#846bd1222323036f7a3515613704386399702bd3" + integrity sha512-d78ivVEzu7Tn0ZphUUaL43+jVPKTMPFGtmgtz1D0LrFn7cY3K8CdrvibuLz2AAkHBLKZtR8DMbB2ukRYFk987A== + dependencies: + acorn "7.1.1" + elliptic "6.5.4" + es6-promise "4.2.8" + nan "2.14.0" + optionalDependencies: + secp256k1 "3.7.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -3378,6 +4418,19 @@ elliptic@6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +elliptic@^6.4.0, elliptic@^6.4.1, elliptic@^6.5.7: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + elliptic@^6.5.2, elliptic@^6.5.4: version "6.5.7" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" @@ -3436,6 +4489,15 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-polyfill@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/error-polyfill/-/error-polyfill-0.1.3.tgz#df848b61ad8834f7a5db69a70b9913df86721d15" + integrity sha512-XHJk60ufE+TG/ydwp4lilOog549iiQF2OAPhkk9DdiYWMrltz5yhDz/xnKuenNwP7gy3dsibssO5QpVhkrSzzg== + dependencies: + capability "^0.2.5" + o3 "^1.0.3" + u3 "^0.1.1" + es-define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" @@ -3448,7 +4510,7 @@ es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es6-promise@^4.0.3: +es6-promise@4.2.8, es6-promise@^4.0.3: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== @@ -3625,6 +4687,19 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +eth-crypto@^2.6.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/eth-crypto/-/eth-crypto-2.7.0.tgz#b859bf4f45660750fa144d74281b5560e362085d" + integrity sha512-MWbDl7OAoBAjkF2a7tklffAJv68uDI/MGPJKontt460nldJ8/2xT4cQacS8sGa6XJlon4ux1nAVzRoa4GxspOQ== + dependencies: + "@babel/runtime" "7.26.0" + "@ethereumjs/tx" "3.5.2" + "@types/bn.js" "5.1.6" + eccrypto "1.1.6" + ethereumjs-util "7.1.5" + ethers "5.7.2" + secp256k1 "5.0.1" + eth-gas-reporter@^0.2.25: version "0.2.27" resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz#928de8548a674ed64c7ba0bf5795e63079150d4e" @@ -3700,6 +4775,17 @@ ethereumjs-abi@^0.6.8: bn.js "^4.11.8" ethereumjs-util "^6.0.0" +ethereumjs-util@7.1.5, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" @@ -3713,18 +4799,7 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.4: - version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" - integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethers@^5.7.0, ethers@^5.7.1, ethers@^5.7.2: +ethers@5.7.2, ethers@^5.7.0, ethers@^5.7.1, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -3773,6 +4848,19 @@ ethers@^6.13.2: tslib "2.4.0" ws "8.17.1" +ethers@^6.13.4: + version "6.13.4" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.4.tgz#bd3e1c3dc1e7dc8ce10f9ffb4ee40967a651b53c" + integrity sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -4022,7 +5110,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.15.6: +follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.4, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -4032,6 +5120,15 @@ forge-std@^1.1.2: resolved "https://registry.yarnpkg.com/forge-std/-/forge-std-1.1.2.tgz#f4a0eda103538d56f9c563f3cd1fa2fd01bd9378" integrity sha512-Wfb0iAS9PcfjMKtGpWQw9mXzJxrWD62kJCUqqLcyuI0+VRtJ3j20XembjF3kS20qELYdXft1vD/SPFVWVKMFOw== +form-data@4.0.0, form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@^2.2.0: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" @@ -4041,15 +5138,6 @@ form-data@^2.2.0: combined-stream "^1.0.6" mime-types "^2.1.12" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -4251,7 +5339,7 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.1.2, glob@^7.1.3: +glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -4304,6 +5392,14 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globalthis@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + globby@^10.0.1: version "10.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" @@ -4330,6 +5426,11 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +google-protobuf@^3.14.0, google-protobuf@^3.17.3, google-protobuf@^3.21.0: + version "3.21.4" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.4.tgz#2f933e8b6e5e9f8edde66b7be0024b68f77da6c9" + integrity sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ== + gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -4347,6 +5448,18 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphql-tag@^2.12.6: + version "2.12.6" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" + integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== + dependencies: + tslib "^2.1.0" + +graphql@^16.3.0: + version "16.9.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" + integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" @@ -4482,7 +5595,7 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.2: +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== @@ -4533,6 +5646,11 @@ he@1.2.0, he@^1.2.0: resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== +hi-base32@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/hi-base32/-/hi-base32-0.5.1.tgz#1279f2ddae2673219ea5870c2121d2a33132857e" + integrity sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4542,6 +5660,13 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -4575,6 +5700,17 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-errors@^1.7.2: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + http-response-object@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" @@ -4582,6 +5718,11 @@ http-response-object@^3.0.1: dependencies: "@types/node" "^10.0.3" +http-status-codes@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.3.0.tgz#987fefb28c69f92a43aecc77feec2866349a8bfc" + integrity sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA== + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -4665,7 +5806,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -4802,6 +5943,11 @@ is-wsl@^2.1.1: dependencies: is-docker "^2.0.0" +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -4840,6 +5986,24 @@ isows@1.0.4: resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.4.tgz#810cd0d90cc4995c26395d2aa4cfa4037ebdf061" integrity sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ== +jayson@^4.0.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.3.tgz#db9be2e4287d9fef4fc05b5fe367abe792c2eee8" + integrity sha512-LtXh5aYZodBZ9Fc3j6f2w+MTNcnxteMOrb+QgIouguGOulWi0lieEkOUg+HkjjFs0DGoWDds6bi4E9hpNFLulQ== + dependencies: + "@types/connect" "^3.4.33" + "@types/node" "^12.12.54" + "@types/ws" "^7.4.4" + JSONStream "^1.3.5" + commander "^2.20.3" + delay "^5.0.0" + es6-promisify "^5.0.0" + eyes "^0.1.8" + isomorphic-ws "^4.0.1" + json-stringify-safe "^5.0.1" + uuid "^8.3.2" + ws "^7.5.10" + jayson@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.2.tgz#443c26a8658703e0b2e881117b09395d88b6982e" @@ -4858,6 +6022,11 @@ jayson@^4.1.1: uuid "^8.3.2" ws "^7.5.10" +js-base64@^3.6.1: + version "3.7.7" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.7.tgz#e51b84bf78fbf5702b9541e2cb7bfcb893b43e79" + integrity sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw== + js-cookie@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" @@ -4868,12 +6037,22 @@ js-sdsl@^4.1.4: resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" integrity sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w== +js-sha256@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" + integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== + js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-tokens@^4.0.0: +js-sha512@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha512/-/js-sha512-0.8.0.tgz#dd22db8d02756faccf19f218e3ed61ec8249f7d4" + integrity sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -4893,6 +6072,18 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jscrypto@^1.0.1, jscrypto@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/jscrypto/-/jscrypto-1.0.3.tgz#598febca2a939d6f679c54f56e1fe364cef30cc9" + integrity sha512-lryZl0flhodv4SZHOqyb1bx5sKcJxj0VBo0Kzb4QMAg3L021IC9uGpl0RCZa+9KJwlRGSK2C80ITcwbe19OKLQ== + +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -4978,11 +6169,20 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -jsonschema@^1.2.4: +jsonschema@^1.2.4, jsonschema@^1.4.0: version "1.4.1" resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== +keccak256@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/keccak256/-/keccak256-1.0.6.tgz#dd32fb771558fed51ce4e45a035ae7515573da58" + integrity sha512-8GLiM01PkdJVGUhR1e6M/AvWnSqYS0HaERI+K/QtStGDGlSTx2B1zTqZk4Zlqu5TxHJNTxWAdP9Y+WI50OApUw== + dependencies: + bn.js "^5.2.0" + buffer "^6.0.3" + keccak "^3.0.2" + keccak@^3.0.0, keccak@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" @@ -5066,11 +6266,30 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +libsodium-wrappers@^0.7.6: + version "0.7.15" + resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.15.tgz#53f13e483820272a3d55b23be2e34402ac988055" + integrity sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ== + dependencies: + libsodium "^0.7.15" + +libsodium@^0.7.15: + version "0.7.15" + resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.15.tgz#ac284e3dcb1c29ae9526c5581cdada6a072f6d20" + integrity sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +link-module-alias@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/link-module-alias/-/link-module-alias-1.2.0.tgz#6a3b7b014cfe18b2759a1222fffce6a40fc120e4" + integrity sha512-ahPjXepbSVKbahTB6LxR//VHm8HPfI+QQygCH+E82spBY4HR5VPJTvlhKBc9F7muVxnS6C1rRfoPOXAbWO/fyw== + dependencies: + chalk "^2.4.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -5153,6 +6372,11 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== +lodash.values@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" + integrity sha512-r0RwvdCv8id9TUblb/O7rYPwVy6lerCbcawrfdo9iC/1t1wsNMJknO79WNBgwkH0hIeJ08jmvvESbFpNb4jH0Q== + lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -5178,6 +6402,23 @@ logform@^2.6.0, logform@^2.6.1: safe-stable-stringify "^2.3.1" triple-beam "^1.3.0" +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + +long@^5.0.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loupe@^2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" @@ -5226,7 +6467,7 @@ map-obj@^1.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== -map-obj@^4.0.0: +map-obj@^4.0.0, map-obj@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== @@ -5366,7 +6607,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +"minimatch@2 || 3", minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -5410,7 +6651,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -5536,6 +6777,21 @@ murmur-128@^0.2.1: fmix "^0.1.0" imul "^1.0.0" +mustache@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" + integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== + +nan@2.14.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nan@^2.13.2, nan@^2.14.0: + version "2.22.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3" + integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== + nanoid@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" @@ -5556,6 +6812,23 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +near-api-js@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/near-api-js/-/near-api-js-1.1.0.tgz#907e807f052c1f043c6fbf28f61872de3c02235a" + integrity sha512-qYKv1mYsaDZc2uYndhS+ttDhR9+60qFc+ZjD6lWsAxr3ZskMjRwPffDGQZYhC7BRDQMe1HEbk6d5mf+TVm0Lqg== + dependencies: + bn.js "5.2.1" + borsh "^0.7.0" + bs58 "^4.0.0" + depd "^2.0.0" + error-polyfill "^0.1.3" + http-errors "^1.7.2" + js-sha256 "^0.9.0" + mustache "^4.0.0" + node-fetch "^2.6.1" + text-encoding-utf-8 "^1.0.2" + tweetnacl "^1.0.1" + negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -5579,6 +6852,11 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + node-emoji@^1.10.0: version "1.11.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" @@ -5619,6 +6897,14 @@ nofilter@^3.1.0: resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== +noms@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859" + integrity sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow== + dependencies: + inherits "^2.0.1" + readable-stream "~1.0.31" + nopt@3.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -5666,7 +6952,14 @@ number-to-bn@1.7.0: bn.js "4.11.6" strip-hex-prefix "1.0.0" -object-assign@^4.1.0: +o3@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/o3/-/o3-1.0.3.tgz#192ce877a882dfa6751f0412a865fafb2da1dac0" + integrity sha512-f+4n+vC6s4ysy7YO7O2gslWZBUu8Qj2i2OUJOvjRxQva7jVjYjB29jrr9NCjmxZQR0gzrOcv1RnqoYOeMs5VRQ== + dependencies: + capability "^0.2.5" + +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -5727,6 +7020,16 @@ openzeppelin-solidity@^4.8.1: resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-4.8.1.tgz#2ab492a5a53a5520401e94df36e43807de7a3b50" integrity sha512-KM0pVpfrCBdifqN2ZeJZFvFuoGz3GmI4Ty/ceKNkcaf7VVWo/rLOfc5EiLh+Ukb5NadNmYo8WMeGhFA8hVWDpg== +optimism@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.1.tgz#5cf16847921413dbb0ac809907370388b9c6335f" + integrity sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ== + dependencies: + "@wry/caches" "^1.0.0" + "@wry/context" "^0.7.0" + "@wry/trie" "^0.5.0" + tslib "^2.3.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -5991,6 +7294,15 @@ promise@^8.0.0: dependencies: asap "~2.0.6" +prop-types@^15.7.2: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + proper-lockfile@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" @@ -6000,6 +7312,43 @@ proper-lockfile@^4.1.1: retry "^0.12.0" signal-exit "^3.0.2" +protobufjs@^6.8.8, protobufjs@~6.11.2, protobufjs@~6.11.3: + version "6.11.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" + integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" ">=13.7.0" + long "^4.0.0" + +protobufjs@^7.0.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" + integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -6062,6 +7411,11 @@ raw-body@2.5.2, raw-body@^2.4.1: iconv-lite "0.4.24" unpipe "1.0.0" +react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" @@ -6090,7 +7444,7 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.4.0, readable-stre string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.2.2: +readable-stream@^2.2.2, readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -6103,6 +7457,16 @@ readable-stream@^2.2.2: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@~1.0.31: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -6147,6 +7511,11 @@ regenerator-runtime@^0.14.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== +rehackt@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.1.0.tgz#a7c5e289c87345f70da8728a7eb878e5d03c696b" + integrity sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw== + req-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" @@ -6214,6 +7583,11 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.8.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +response-iterator@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/response-iterator/-/response-iterator-0.2.6.tgz#249005fb14d2e4eeb478a3f735a28fd8b4c9f3da" + integrity sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw== + retry@0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" @@ -6243,6 +7617,11 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +ripemd160-min@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/ripemd160-min/-/ripemd160-min-0.0.6.tgz#a904b77658114474d02503e819dcc55853b67e62" + integrity sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A== + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -6258,6 +7637,18 @@ rlp@^2.2.3, rlp@^2.2.4: dependencies: bn.js "^5.2.0" +rpc-websockets@^7.5.1: + version "7.11.2" + resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.11.2.tgz#582910c425b9f2c860327481c1d1e0e431bf4a6d" + integrity sha512-pL9r5N6AVHlMN/vT98+fcO+5+/UcPLf/4tq+WUaid/PPUGS/ttJ3y8e9IqmaWKtShNAysMSjkczuEA49NuV7UQ== + dependencies: + eventemitter3 "^4.0.7" + uuid "^8.3.2" + ws "^8.5.0" + optionalDependencies: + bufferutil "^4.0.1" + utf-8-validate "^5.0.2" + rpc-websockets@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.0.2.tgz#4c1568d00b8100f997379a363478f41f8f4b242c" @@ -6293,6 +7684,13 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== +rxjs@^7.4.0, rxjs@^7.5.6, rxjs@^7.8.0: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -6338,6 +7736,29 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +secp256k1@3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.7.1.tgz#12e473e0e9a7c2f2d4d4818e722ad0e14cc1e2f1" + integrity sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g== + dependencies: + bindings "^1.5.0" + bip66 "^1.1.5" + bn.js "^4.11.8" + create-hash "^1.2.0" + drbg.js "^1.0.1" + elliptic "^6.4.1" + nan "^2.14.0" + safe-buffer "^5.1.2" + +secp256k1@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.1.tgz#dc2c86187d48ff2da756f0f7e96417ee03c414b1" + integrity sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA== + dependencies: + elliptic "^6.5.7" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" + secp256k1@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" @@ -6347,6 +7768,15 @@ secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" +secp256k1@^4.0.2, secp256k1@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.4.tgz#58f0bfe1830fe777d9ca1ffc7574962a8189f8ab" + integrity sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw== + dependencies: + elliptic "^6.5.7" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" + "semver@2 || 3 || 4 || 5", semver@^5.5.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -6450,6 +7880,13 @@ sha1@^1.1.1: charenc ">= 0.0.1" crypt ">= 0.0.1" +sha3@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/sha3/-/sha3-2.1.4.tgz#000fac0fe7c2feac1f48a25e7a31b52a6492cc8f" + integrity sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg== + dependencies: + buffer "6.0.3" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -6462,7 +7899,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@^0.8.3: +shelljs@^0.8.3, shelljs@^0.8.5: version "0.8.5" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== @@ -6471,6 +7908,14 @@ shelljs@^0.8.3: interpret "^1.0.0" rechoir "^0.6.2" +shx@^0.3.2: + version "0.3.4" + resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.4.tgz#74289230b4b663979167f94e1935901406e40f02" + integrity sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g== + dependencies: + minimist "^1.2.3" + shelljs "^0.8.5" + side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" @@ -6527,6 +7972,15 @@ snake-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" +snakecase-keys@^5.1.2, snakecase-keys@^5.4.1: + version "5.5.0" + resolved "https://registry.yarnpkg.com/snakecase-keys/-/snakecase-keys-5.5.0.tgz#fbf9ca4a47fcc37c7496d00c6d9e455da9750403" + integrity sha512-r3kRtnoPu3FxGJ3fny6PKNnU3pteb29o6qAa0ugzhSseKNWRkw1dw8nIjXMyyKaU9vQxxVIE62Mb3bKbdrgpiw== + dependencies: + map-obj "^4.1.0" + snake-case "^3.0.4" + type-fest "^3.12.0" + solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -6699,6 +8153,16 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +"statuses@>= 1.5.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +store2@^2.12.0: + version "2.14.3" + resolved "https://registry.yarnpkg.com/store2/-/store2-2.14.3.tgz#24077d7ba110711864e4f691d2af941ec533deb5" + integrity sha512-4QcZ+yx7nzEFiV4BMLnr/pRa5HYzNITX2ri0Zh6sT9EyQHbBHacC6YigllUPU9X3D0f/22QCgfokpKs52YRrUg== + string-format@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" @@ -6728,6 +8192,11 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -6783,6 +8252,11 @@ superstruct@^0.15.4: resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.5.tgz#0f0a8d3ce31313f0d84c6096cd4fa1bfdedc9dab" integrity sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ== +superstruct@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== + superstruct@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" @@ -6821,6 +8295,16 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +symbol-observable@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-2.0.3.tgz#5b521d3d07a43c351055fa43b8355b62d33fd16a" + integrity sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA== + +symbol-observable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" + integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== + sync-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" @@ -6895,6 +8379,14 @@ then-request@^6.0.0: promise "^8.0.0" qs "^6.4.0" +through2@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + through2@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" @@ -6907,6 +8399,17 @@ through2@^4.0.0: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== +tiny-secp256k1@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/tiny-secp256k1/-/tiny-secp256k1-1.1.7.tgz#0c1b6b9d2d93404f9093dc7e287b0aa834480573" + integrity sha512-eb+F6NabSnjbLwNoC+2o5ItbmP1kg7HliWue71JgLegQt6A5mTN8YbvTLCazdlg6e5SV6A+r8OGvZYskdlmhqQ== + dependencies: + bindings "^1.3.0" + bn.js "^4.11.8" + create-hmac "^1.1.7" + elliptic "^6.4.0" + nan "^2.13.2" + tmp@0.0.33, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -6914,6 +8417,11 @@ tmp@0.0.33, tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -6998,6 +8506,13 @@ ts-generator@^0.1.1: resolve "^1.8.1" ts-essentials "^1.0.0" +ts-invariant@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c" + integrity sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ== + dependencies: + tslib "^2.1.0" + ts-mocha@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" @@ -7055,21 +8570,21 @@ tslib@2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@2.7.0, tslib@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3, tslib@^2.3.1, tslib@^2.6.2: +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.6.2: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -tslib@^2.4.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" - integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== - tsort@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" @@ -7087,7 +8602,7 @@ tweetnacl-util@^0.15.1: resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== -tweetnacl@^1.0.3: +tweetnacl@1.0.3, tweetnacl@^1.0.1, tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -7141,6 +8656,11 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^3.12.0: + version "3.13.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.13.1.tgz#bb744c1f0678bea7543a2d1ec24e83e68e8c8706" + integrity sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -7170,6 +8690,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== +typeforce@^1.11.5: + version "1.18.0" + resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" + integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== + typescript@^4.3.5, typescript@^4.9.3: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" @@ -7195,6 +8720,11 @@ typical@^5.2.0: resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== +u3@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/u3/-/u3-0.1.1.tgz#5f52044f42ee76cd8de33148829e14528494b73b" + integrity sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w== + uglify-js@^3.1.4: version "3.19.3" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" @@ -7215,6 +8745,11 @@ undici-types@~6.19.2: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== + undici@^5.14.0: version "5.28.4" resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" @@ -7242,6 +8777,11 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -7249,7 +8789,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -utf-8-validate@^5.0.2: +utf-8-validate@^5.0.2, utf-8-validate@^5.0.5: version "5.0.10" resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== @@ -7338,6 +8878,11 @@ viem@^2.9.28: webauthn-p256 "0.0.5" ws "8.17.1" +vlq@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-2.0.4.tgz#6057b85729245b9829e3cc7755f95b228d4fe041" + integrity sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA== + web3-utils@^1.3.6: version "1.10.4" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.4.tgz#0daee7d6841641655d8b3726baf33b08eda1cbec" @@ -7400,6 +8945,13 @@ which@^1.1.1, which@^1.3.1: dependencies: isexe "^2.0.0" +wif@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" + integrity sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ== + dependencies: + bs58check "<3.0.0" + winston-transport@^4.7.0: version "4.7.1" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.1.tgz#52ff1bcfe452ad89991a0aaff9c3b18e7f392569" @@ -7483,7 +9035,7 @@ ws@8.17.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== -ws@^7.4.6, ws@^7.5.10: +ws@^7, ws@^7.4.6, ws@^7.5.10, ws@^7.5.8, ws@^7.5.9: version "7.5.10" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== @@ -7493,6 +9045,19 @@ ws@^8.5.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== +xstream@^11.14.0: + version "11.14.0" + resolved "https://registry.yarnpkg.com/xstream/-/xstream-11.14.0.tgz#2c071d26b18310523b6877e86b4e54df068a9ae5" + integrity sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw== + dependencies: + globalthis "^1.0.1" + symbol-observable "^2.0.3" + +xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -7538,7 +9103,7 @@ yargs-unparser@2.0.0, yargs-unparser@^2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@16.2.0, yargs@^16.2.0: +yargs@16.2.0, yargs@^16.1.0, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -7579,6 +9144,18 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zen-observable-ts@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58" + integrity sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg== + dependencies: + zen-observable "0.8.15" + +zen-observable@0.8.15: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== + zksync-web3@^0.14.3: version "0.14.4" resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.4.tgz#0b70a7e1a9d45cc57c0971736079185746d46b1f" From f08a6facdf346f82e26e4de31566270c1bcf1c3b Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Thu, 5 Dec 2024 06:35:38 +0100 Subject: [PATCH 11/31] refactor(solana): adds some fx comments --- packages/solana/programs/adapter/src/lib.rs | 25 ++- .../programs/debridge-reporter/src/lib.rs | 6 +- packages/solana/programs/hashi/src/lib.rs | 27 ++- packages/solana/tests/adapter.ts | 46 ++--- packages/solana/tests/hashi.ts | 160 +++++++++--------- 5 files changed, 159 insertions(+), 105 deletions(-) diff --git a/packages/solana/programs/adapter/src/lib.rs b/packages/solana/programs/adapter/src/lib.rs index 8ea41a88..63488fc4 100644 --- a/packages/solana/programs/adapter/src/lib.rs +++ b/packages/solana/programs/adapter/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("E31NDsJknUaJ1VKGBCePkcZysajUqqFw5pDFAz1fFAGu"); +declare_id!("EUDyxkHVf9NBRTREn69rcFDAEefmHj3UrLJV14vnqACp"); pub mod contexts; pub mod state; @@ -12,6 +12,29 @@ pub use state::*; pub mod adapter { use super::*; + /// Stores a hash in a `HashAccount` for later validation or retrieval. + /// + /// This function updates the provided `HashAccount` with the specified adapter ID, domain, ID, and hash. + /// It is primarily used to persist hash data in a consistent and structured way for subsequent operations, + /// such as validation or consensus checks. + /// + /// # Arguments + /// + /// - `ctx`: A `Context` object containing the `HashAccount` to be updated. + /// - `adapter_id`: A 32-byte identifier representing the adapter associated with this hash. + /// - `domain`: A 32-byte domain identifier that contextualizes the hash within a specific scope. + /// - `id`: A 32-byte identifier uniquely identifying the subject or entity associated with this hash. + /// - `hash`: A 32-byte hash value to be stored in the `HashAccount`. + /// + /// # Returns + /// + /// - `Ok(())`: If the hash is successfully stored in the `HashAccount`. + /// + /// # Notes + /// + /// - This function assumes that the provided `HashAccount` is correctly initialized and writable. + /// - The emitted event allows external systems or users to monitor the stored hash details without + /// directly querying the on-chain state. pub fn store_hash( ctx: Context, adapter_id: [u8; 32], diff --git a/packages/solana/programs/debridge-reporter/src/lib.rs b/packages/solana/programs/debridge-reporter/src/lib.rs index 7136837f..2891ed62 100644 --- a/packages/solana/programs/debridge-reporter/src/lib.rs +++ b/packages/solana/programs/debridge-reporter/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("2TvQ6gqQGAifdV2cQ1f8zHGYV2t6wPUNTKzpcALt8rX7"); +declare_id!("7GPwvvhq33fTYuDyfA1JVz4fp3XkdcmjerJWpUkxjrC2"); pub mod contexts; @@ -21,8 +21,10 @@ pub mod debridge_reporter { ) -> Result<()> { let slot_hash = get_slot(&ctx.accounts.slot_hashes, slot_number)?; let message = Message::from((slot_number, slot_hash)); + let mut payload: Vec = Vec::new(); + message.serialize(&mut payload)?; sending::invoke_send_message( - message.try_to_vec()?, + payload, target_chain_id, receiver, 0, // execution_fee = 0 means auto claim diff --git a/packages/solana/programs/hashi/src/lib.rs b/packages/solana/programs/hashi/src/lib.rs index 1b9d867d..40544f65 100644 --- a/packages/solana/programs/hashi/src/lib.rs +++ b/packages/solana/programs/hashi/src/lib.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use adapter::HashAccount; -declare_id!("EyqiZf8Yt2CgVU5yPsj5e4EiGXeKrLhefWBn7CSqKPMC"); +declare_id!("76cEKq1qRhBLn56kZdG1Hj7UHXggcNfinbnKejXDnMpU"); pub mod contexts; pub mod error; @@ -15,6 +15,31 @@ pub use error::ErrorCode; pub mod hashi { use super::*; + /// Verifies hashes against a threshold for validation. + /// + /// This function checks if the number of occurrences of any hash associated with the provided + /// adapter IDs, domain, and ID meets or exceeds the specified threshold. It is used for consensus + /// or validation mechanisms where a certain number of matching hashes are required to proceed. + /// + /// # Arguments + /// + /// - `ctx`: A `Context` object containing accounts and other data required for the validation process. + /// - `adapter_ids`: A vector of adapter IDs, each uniquely identifying an adapter associated with + /// the hashes being validated. + /// - `domain`: A 32-byte domain identifier for contextual validation of the hashes. + /// - `id`: A 32-byte identifier associated with the hashes being validated. + /// - `threshold`: The minimum number of occurrences a hash must have to pass validation. + /// + /// # Returns + /// + /// - `Ok(())`: If the validation succeeds and the threshold is met. + /// - Relevant `ErrorCode` if validation fails due to mismatched IDs, domains, or insufficient hash occurrences. + /// + /// # Notes + /// + /// This function ensures data integrity by requiring alignment between the provided adapter IDs, + /// domain, and ID with the deserialized `HashAccount` data. It is robust against invalid inputs + /// and enforces a strict validation pipeline. pub fn check_hash_with_threshold( ctx: Context, adapter_ids: Vec<[u8; 32]>, diff --git a/packages/solana/tests/adapter.ts b/packages/solana/tests/adapter.ts index 869a2e5b..911f8974 100644 --- a/packages/solana/tests/adapter.ts +++ b/packages/solana/tests/adapter.ts @@ -16,27 +16,29 @@ describe("adapter", () => { const adapter = anchor.workspace.Adapter as Program - it("should store an hash", async () => { - const id = 1 - const hash = Array.from( - Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), - ) - - const [hashAccountPDA] = await PublicKey.findProgramAddressSync( - [Buffer.from("hash_account", "utf-8"), ADAPTER_ID, DOMAIN, intToBytes32Buff(id)], - adapter.programId, - ) - - await adapter.methods - .storeHash(ADAPTER_ID, DOMAIN, intToBytes32Buff(id), hash) - .accounts({ - hashAccount: hashAccountPDA, - user: provider.wallet.publicKey, - systemProgram: SystemProgram.programId, - }) - .rpc() - - const hashAccount = await adapter.account.hashAccount.fetch(hashAccountPDA) - expect(hashAccount.hash).to.be.deep.eq(hash) + describe("store_hash", () => { + it("should store an hash", async () => { + const id = 1 + const hash = Array.from( + Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), + ) + + const [hashAccountPDA] = await PublicKey.findProgramAddressSync( + [Buffer.from("hash_account", "utf-8"), ADAPTER_ID, DOMAIN, intToBytes32Buff(id)], + adapter.programId, + ) + + await adapter.methods + .storeHash(ADAPTER_ID, DOMAIN, intToBytes32Buff(id), hash) + .accounts({ + hashAccount: hashAccountPDA, + user: provider.wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .rpc() + + const hashAccount = await adapter.account.hashAccount.fetch(hashAccountPDA) + expect(hashAccount.hash).to.be.deep.eq(hash) + }) }) }) diff --git a/packages/solana/tests/hashi.ts b/packages/solana/tests/hashi.ts index 97bc9146..7ef7356e 100644 --- a/packages/solana/tests/hashi.ts +++ b/packages/solana/tests/hashi.ts @@ -21,85 +21,40 @@ describe("hashi", () => { const hashi = anchor.workspace.Hashi as Program const adapter = anchor.workspace.Adapter as Program - it("should not fail if the majority of adapters agree on an hash", async () => { - const threshold = 2 - const id = 1 - const hashes = [ - Array.from( - Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), - ), - Array.from( - Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), - ), - Array.from( - Uint8Array.from(Buffer.from("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "hex")), - ), - ] + describe("check_hash_with_threshold", () => { + it("should not fail if the majority of adapters agree on an hash", async () => { + const threshold = 2 + const id = 1 + const hashes = [ + Array.from( + Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), + ), + Array.from( + Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), + ), + Array.from( + Uint8Array.from(Buffer.from("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "hex")), + ), + ] - const hashAccountsPDA = [] - for (const [index, adapterId] of ADAPTER_IDS.entries()) { - const [hashAccountPDA] = await PublicKey.findProgramAddressSync( - [Buffer.from("hash_account", "utf-8"), adapterId, DOMAIN, intToBytes32Buff(id)], - adapter.programId, - ) - - await adapter.methods - .storeHash(adapterId, DOMAIN, intToBytes32Buff(id), hashes[index]) - .accounts({ - hashAccount: hashAccountPDA, - user: provider.wallet.publicKey, - systemProgram: SystemProgram.programId, - }) - .rpc() - hashAccountsPDA.push(hashAccountPDA) - } - - await hashi.methods - .checkHashWithThreshold(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) - .remainingAccounts( - hashAccountsPDA.map((_hashAccountPDA) => ({ - isSigner: false, - isWritable: false, - pubkey: _hashAccountPDA, - })), - ) - .rpc() - }) - - it("should fail if the majority of adapters doesn't agree on an hash", async () => { - const threshold = 2 - const id = 1 - const hashes = [ - Array.from( - Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), - ), - Array.from( - Uint8Array.from(Buffer.from("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "hex")), - ), - Array.from( - Uint8Array.from(Buffer.from("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", "hex")), - ), - ] + const hashAccountsPDA = [] + for (const [index, adapterId] of ADAPTER_IDS.entries()) { + const [hashAccountPDA] = await PublicKey.findProgramAddressSync( + [Buffer.from("hash_account", "utf-8"), adapterId, DOMAIN, intToBytes32Buff(id)], + adapter.programId, + ) - const hashAccountsPDA = [] - for (const [index, adapterId] of ADAPTER_IDS.entries()) { - const [hashAccountPDA] = await PublicKey.findProgramAddressSync( - [Buffer.from("hash_account", "utf-8"), adapterId, DOMAIN, intToBytes32Buff(id)], - adapter.programId, - ) + await adapter.methods + .storeHash(adapterId, DOMAIN, intToBytes32Buff(id), hashes[index]) + .accounts({ + hashAccount: hashAccountPDA, + user: provider.wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .rpc() + hashAccountsPDA.push(hashAccountPDA) + } - await adapter.methods - .storeHash(adapterId, DOMAIN, intToBytes32Buff(id), hashes[index]) - .accounts({ - hashAccount: hashAccountPDA, - user: provider.wallet.publicKey, - systemProgram: SystemProgram.programId, - }) - .rpc() - hashAccountsPDA.push(hashAccountPDA) - } - - try { await hashi.methods .checkHashWithThreshold(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) .remainingAccounts( @@ -110,8 +65,55 @@ describe("hashi", () => { })), ) .rpc() - } catch (_err) { - expect(_err.error.errorCode.code).to.be.eq("ThresholdNotMet") - } + }) + + it("should fail if the majority of adapters doesn't agree on an hash", async () => { + const threshold = 2 + const id = 1 + const hashes = [ + Array.from( + Uint8Array.from(Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex")), + ), + Array.from( + Uint8Array.from(Buffer.from("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "hex")), + ), + Array.from( + Uint8Array.from(Buffer.from("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", "hex")), + ), + ] + + const hashAccountsPDA = [] + for (const [index, adapterId] of ADAPTER_IDS.entries()) { + const [hashAccountPDA] = await PublicKey.findProgramAddressSync( + [Buffer.from("hash_account", "utf-8"), adapterId, DOMAIN, intToBytes32Buff(id)], + adapter.programId, + ) + + await adapter.methods + .storeHash(adapterId, DOMAIN, intToBytes32Buff(id), hashes[index]) + .accounts({ + hashAccount: hashAccountPDA, + user: provider.wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .rpc() + hashAccountsPDA.push(hashAccountPDA) + } + + try { + await hashi.methods + .checkHashWithThreshold(ADAPTER_IDS, DOMAIN, intToBytes32Buff(id), new anchor.BN(threshold)) + .remainingAccounts( + hashAccountsPDA.map((_hashAccountPDA) => ({ + isSigner: false, + isWritable: false, + pubkey: _hashAccountPDA, + })), + ) + .rpc() + } catch (_err) { + expect(_err.error.errorCode.code).to.be.eq("ThresholdNotMet") + } + }) }) }) From b1589ba717d33a72b53fc113289614545b973268 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Mon, 9 Dec 2024 15:30:09 +0100 Subject: [PATCH 12/31] feat(solana): adds slot dispatch within wormhole_reporter.initialize --- .../src/contexts/initialize.rs | 5 ++++ .../programs/wormhole-reporter/src/lib.rs | 27 +++++++------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs index 843621e7..48d27e3b 100644 --- a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs +++ b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs @@ -1,4 +1,5 @@ use anchor_lang::prelude::*; +use anchor_lang::solana_program::sysvar; use wormhole_anchor_sdk::wormhole::{self, program::Wormhole}; use crate::state::{Config, WormholeEmitter}; @@ -100,4 +101,8 @@ pub struct Initialize<'info> { /// System program. pub system_program: Program<'info, System>, + + /// CHECK: We are reading from SlotHashes sysvar the latest slot hash + #[account(address = sysvar::slot_hashes::ID)] + pub slot_hashes: AccountInfo<'info>, } diff --git a/packages/solana/programs/wormhole-reporter/src/lib.rs b/packages/solana/programs/wormhole-reporter/src/lib.rs index 7e2c7c39..6722a234 100644 --- a/packages/solana/programs/wormhole-reporter/src/lib.rs +++ b/packages/solana/programs/wormhole-reporter/src/lib.rs @@ -8,7 +8,7 @@ pub use contexts::*; pub use error::ErrorCode; pub use state::*; -declare_id!("3ESz1nYWmkdp9A3SByK7mbf9toDSRPvJADDF6pz45qZG"); +declare_id!("AeUyN4y9cvEzCDTVUy3ZPhrYw7i44kNBsqMeGysZfWid"); #[program] pub mod wormhole_reporter { @@ -20,14 +20,12 @@ pub mod wormhole_reporter { /// This instruction initializes the program config, which is meant /// to store data useful for other instructions. The config specifies - /// an owner (e.g. multisig) and should be read-only for every instruction - /// in this example. This owner will be checked for designated owner-only - /// instructions like [`register_emitter`](register_emitter). + /// an owner (e.g. multisig) and should be read-only for every instruction. /// /// # Arguments /// /// * `ctx` - `Initialize` contexts - pub fn initialize(ctx: Context) -> Result<()> { + pub fn initialize(ctx: Context, slot_number: u64) -> Result<()> { let config = &mut ctx.accounts.config; // Set the owner of the config (effectively the owner of the program). @@ -62,8 +60,6 @@ pub mod wormhole_reporter { // Wormhole program that there is an actual account associated with the // emitter PDA. The emitter PDA is just a mechanism to have the program // sign for the `wormhole::post_message` instruction. - // - // But for fun, we will store our emitter's bump for convenience. ctx.accounts.wormhole_emitter.bump = ctx.bumps.wormhole_emitter; { @@ -105,14 +101,14 @@ pub mod wormhole_reporter { // account with an address derived by this program so we can // use the PDA to access and deserialize the message data. // - // In our example, we use method #2. + // we use method #2. let wormhole_emitter = &ctx.accounts.wormhole_emitter; let config = &ctx.accounts.config; - // If anyone were to care about the first message this program - // emits, he can deserialize it to find the program with which - // the emitter PDA was derived. - let payload = ctx.program_id.try_to_vec()?; + let slot_hash = get_slot(&ctx.accounts.slot_hashes, slot_number)?; + let message = Message::from((slot_number, slot_hash)); + let mut payload: Vec = Vec::new(); + message.serialize(&mut payload)?; wormhole::post_message( CpiContext::new_with_signer( @@ -169,12 +165,7 @@ pub mod wormhole_reporter { /// # Returns /// /// This function returns `Ok(())` on success or a relevant error if the process fails. - pub fn dispatch_slot( - ctx: Context, - /*target_chain_id: [u8; 32], - receiver: Vec,*/ - slot_number: u64, - ) -> Result<()> { + pub fn dispatch_slot(ctx: Context, slot_number: u64) -> Result<()> { // If Wormhole requires a fee before posting a message, we need to // transfer lamports to the fee collector. Otherwise // `wormhole::post_message` will fail. From 18ce29f223abc0ca1bd53f578cb4dbef734d54a8 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Mon, 9 Dec 2024 15:43:26 +0100 Subject: [PATCH 13/31] chore(solana): rn wormhole_reporter feature testnet into devnet --- packages/solana/programs/wormhole-reporter/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solana/programs/wormhole-reporter/Cargo.toml b/packages/solana/programs/wormhole-reporter/Cargo.toml index 78e33669..3059ceda 100644 --- a/packages/solana/programs/wormhole-reporter/Cargo.toml +++ b/packages/solana/programs/wormhole-reporter/Cargo.toml @@ -11,7 +11,7 @@ name = "wormhole_reporter" [features] default = ["mainnet"] mainnet = ["wormhole-anchor-sdk/mainnet"] -testnet = ["wormhole-anchor-sdk/solana-devnet"] +devnet = ["wormhole-anchor-sdk/solana-devnet"] localnet = ["wormhole-anchor-sdk/tilt-devnet"] cpi = ["no-entrypoint"] no-entrypoint = [] From 5a25ba906651bf3854cea303a12128af80fef477 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Mon, 9 Dec 2024 15:49:52 +0100 Subject: [PATCH 14/31] refactor(solana): updates wormhole_reporter tests based on new changes --- packages/solana/tests/wormhole-reporter.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/solana/tests/wormhole-reporter.ts b/packages/solana/tests/wormhole-reporter.ts index e1dd5220..4dd94e64 100644 --- a/packages/solana/tests/wormhole-reporter.ts +++ b/packages/solana/tests/wormhole-reporter.ts @@ -13,10 +13,10 @@ import { AbiCoder } from "ethers" import { WormholeReporter } from "../target/types/wormhole_reporter" -const WORMHOLE_CONTRACTS = CONTRACTS.MAINNET +const WORMHOLE_CONTRACTS = CONTRACTS.TESTNET const CORE_BRIDGE_PID = new PublicKey(WORMHOLE_CONTRACTS.solana.core) -const deriveWormholeMessageKey = (_programId: PublicKeyInitData, _sequence: bigint) => { +export const deriveWormholeMessageKey = (_programId: PublicKeyInitData, _sequence: bigint) => { return deriveAddress( [ Buffer.from("sent"), @@ -44,18 +44,21 @@ describe("wormhole_reporter", () => { describe("initialize", () => { it("should set up the program", async () => { + const slot = await provider.connection.getSlot() + const slotNumberToDispatch = new anchor.BN(slot - 1) + const message = deriveWormholeMessageKey(reporter.programId, 1n) const wormholeAccounts = getPostMessageCpiAccounts(reporter.programId, CORE_BRIDGE_PID, payer.publicKey, message) const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], reporter.programId) - await reporter.methods - .initialize() + .initialize(slotNumberToDispatch) .accounts({ owner: new PublicKey(payer.publicKey), config: configKey, wormholeProgram: new PublicKey(CORE_BRIDGE_PID), + slotHashes: SYSVAR_SLOT_HASHES_PUBKEY, ...wormholeAccounts, - }) + } as any) .signers([payer]) .rpc() @@ -83,7 +86,7 @@ describe("wormhole_reporter", () => { wormholeProgram: new PublicKey(CORE_BRIDGE_PID), slotHashes: SYSVAR_SLOT_HASHES_PUBKEY, ...wormholeAccounts, - }) + } as any) .signers([payer]) .rpc() From de19b017d6a8f6876c2abfcd5568af7e983f7d61 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Mon, 9 Dec 2024 15:50:26 +0100 Subject: [PATCH 15/31] chore(solana): updates debridge-solana-sdk version --- packages/solana/Cargo.lock | 12 +++++++++--- .../solana/programs/debridge-reporter/Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index 248247d3..86e876fb 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -1182,9 +1182,8 @@ dependencies = [ [[package]] name = "debridge-solana-sdk" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac97e77dab5301c48a882cb08277733006aadbf52a7409e8ca69e8da9446d88" +version = "1.0.2" +source = "git+ssh://git@github.com/debridge-finance/debridge-solana-sdk.git#e442dd77f2cab1082a7140be3602314567e4b4b6" dependencies = [ "borsh 0.9.3", "cfg-match", @@ -1194,6 +1193,7 @@ dependencies = [ "lazy_static", "sha3 0.10.8", "solana-program", + "some-to-err", "thiserror", ] @@ -2919,6 +2919,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "some-to-err" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d95fd601e937c6e1fe0f25ef8754008e7bf87e97a8a60a8a60b0a289f7e39ad" + [[package]] name = "spki" version = "0.7.3" diff --git a/packages/solana/programs/debridge-reporter/Cargo.toml b/packages/solana/programs/debridge-reporter/Cargo.toml index 1474468b..8af05c85 100644 --- a/packages/solana/programs/debridge-reporter/Cargo.toml +++ b/packages/solana/programs/debridge-reporter/Cargo.toml @@ -18,6 +18,6 @@ idl-build = ["anchor-lang/idl-build"] [dependencies] anchor-lang = "0.30.1" -debridge-solana-sdk = "1.0.1" +debridge-solana-sdk = { git = "ssh://git@github.com/debridge-finance/debridge-solana-sdk.git", version = "1.0.2" } slots = { path = "../../shared/slots" } message = { path = "../../shared/message" } \ No newline at end of file From 55fdac82871e47c9c286e7a2261bb48454956119 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Tue, 17 Dec 2024 17:27:34 +0100 Subject: [PATCH 16/31] feat(solana): starts snapshotter --- packages/solana/Anchor.toml | 9 +- packages/solana/Cargo.lock | 15 +- packages/solana/Cargo.toml | 2 +- .../solana/programs/snapshotter/Cargo.toml | 20 ++ .../solana/programs/snapshotter/Xargo.toml | 2 + .../src/contexts/calculate_root.rs | 24 +++ .../snapshotter/src/contexts/initialize.rs | 44 +++++ .../programs/snapshotter/src/contexts/mod.rs | 7 + .../snapshotter/src/contexts/subscribe.rs | 21 +++ .../solana/programs/snapshotter/src/error.rs | 21 +++ .../solana/programs/snapshotter/src/lib.rs | 175 +++++++++++++++++ .../programs/snapshotter/src/state/config.rs | 53 ++++++ .../programs/snapshotter/src/state/mod.rs | 3 + packages/solana/tests/snapshotter.ts | 178 ++++++++++++++++++ 14 files changed, 565 insertions(+), 9 deletions(-) create mode 100644 packages/solana/programs/snapshotter/Cargo.toml create mode 100644 packages/solana/programs/snapshotter/Xargo.toml create mode 100644 packages/solana/programs/snapshotter/src/contexts/calculate_root.rs create mode 100644 packages/solana/programs/snapshotter/src/contexts/initialize.rs create mode 100644 packages/solana/programs/snapshotter/src/contexts/mod.rs create mode 100644 packages/solana/programs/snapshotter/src/contexts/subscribe.rs create mode 100644 packages/solana/programs/snapshotter/src/error.rs create mode 100644 packages/solana/programs/snapshotter/src/lib.rs create mode 100644 packages/solana/programs/snapshotter/src/state/config.rs create mode 100644 packages/solana/programs/snapshotter/src/state/mod.rs create mode 100644 packages/solana/tests/snapshotter.ts diff --git a/packages/solana/Anchor.toml b/packages/solana/Anchor.toml index 59f0df86..57809038 100644 --- a/packages/solana/Anchor.toml +++ b/packages/solana/Anchor.toml @@ -5,10 +5,11 @@ resolution = true skip-lint = false [programs.localnet] -adapter = "EUDyxkHVf9NBRTREn69rcFDAEefmHj3UrLJV14vnqACp" -debridge-reporter = "7GPwvvhq33fTYuDyfA1JVz4fp3XkdcmjerJWpUkxjrC2" -hashi = "76cEKq1qRhBLn56kZdG1Hj7UHXggcNfinbnKejXDnMpU" -wormhole-reporter = "3ESz1nYWmkdp9A3SByK7mbf9toDSRPvJADDF6pz45qZG" +snapshotter = "37298hWBczA1od9ytwgSYyhP42WLNiXieAVCxBxAeX9S" +adapter = "4v78nFouRCT7q29cGUoUxeTrwLufsYETH6TFqdiFBonT" +debridge-reporter = "DkJFdedMeprFUzymuZpvXCTqcUt1zc8uz45UgajsKbWH" +hashi = "E5d22pcTFz6YbiNDBxyxQ6kHYdT3qHh4gkxDFTm48FQ" +wormhole-reporter = "48Vq4rpj7tiZKvpVkzmR5kHUTLy6KdL1c4zkFw17cNZw" [registry] url = "https://api.apr.dev" diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index 86e876fb..0602dfe9 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -939,9 +939,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "num-traits", ] @@ -2713,6 +2713,13 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "snapshotter" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + [[package]] name = "solana-frozen-abi" version = "1.18.26" @@ -3064,9 +3071,9 @@ dependencies = [ [[package]] name = "spl-token-2022" -version = "3.0.4" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d1b2851964e257187c0bca43a0de38d0af59192479ca01ac3e2b58b1bd95a" +checksum = "4c39e416aeb1ea0b22f3b2bbecaf7e38a92a1aa8f4a0c5785c94179694e846a0" dependencies = [ "arrayref", "bytemuck", diff --git a/packages/solana/Cargo.toml b/packages/solana/Cargo.toml index c018f5ae..82067007 100644 --- a/packages/solana/Cargo.toml +++ b/packages/solana/Cargo.toml @@ -20,4 +20,4 @@ rev = "6105d7a5591aefa646a95d12b5e8d3f55a9214ef" [patch.crates-io.curve25519-dalek] git = "https://github.com/solana-labs/curve25519-dalek.git" -rev = "b500cdc2a920cd5bff9e2dd974d7b97349d61464" \ No newline at end of file +rev = "b500cdc2a920cd5bff9e2dd974d7b97349d61464" diff --git a/packages/solana/programs/snapshotter/Cargo.toml b/packages/solana/programs/snapshotter/Cargo.toml new file mode 100644 index 00000000..0063eadb --- /dev/null +++ b/packages/solana/programs/snapshotter/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "snapshotter" +version = "0.1.0" +description = "Created with Anchor" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] +name = "snapshotter" + +[features] +default = [] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build"] + +[dependencies] +anchor-lang = "0.30.1" \ No newline at end of file diff --git a/packages/solana/programs/snapshotter/Xargo.toml b/packages/solana/programs/snapshotter/Xargo.toml new file mode 100644 index 00000000..475fb71e --- /dev/null +++ b/packages/solana/programs/snapshotter/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs b/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs new file mode 100644 index 00000000..0d083ef9 --- /dev/null +++ b/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs @@ -0,0 +1,24 @@ +use crate::*; + +#[derive(Accounts)] +pub struct CalculateRoot<'info> { + // The `config` account will be accessed and potentially modified by this instruction. + // The `#[account(...)]` attribute macro applies constraints to this account: + // - `seeds = [Config::SEED_PREFIX]`: The account is derived from a program-derived address (PDA) + // using `Config::SEED_PREFIX` as the seed. This ensures that the correct PDA is referenced. + // - `bump`: Used in combination with the seeds to find the PDA. The `bump` ensures a valid PDA + // that is not already taken by another account. + // - `mut`: The `mut` keyword indicates that this account will be mutated (written to) + // during the instruction execution. + #[account( + seeds = [Config::SEED_PREFIX], + bump, + mut + )] + pub config: Account<'info, Config>, + + // The `clock` field references the Sysvar `Clock` account, which provides the current + // cluster time, slot, epoch, etc. It is read-only and used for time-based logic within + // the instruction if necessary. + pub clock: Sysvar<'info, Clock>, +} diff --git a/packages/solana/programs/snapshotter/src/contexts/initialize.rs b/packages/solana/programs/snapshotter/src/contexts/initialize.rs new file mode 100644 index 00000000..93083f84 --- /dev/null +++ b/packages/solana/programs/snapshotter/src/contexts/initialize.rs @@ -0,0 +1,44 @@ +use crate::*; + +#[derive(Accounts)] +pub struct Initialize<'info> { + // The `owner` is a Signer account, indicating that whoever calls this instruction + // must sign the transaction with their private key. This ensures that the initializer + // has authority. + // `#[account(mut)]` is used here because the `payer` field below uses this account's + // lamports to fund the creation of the `config` account. + #[account(mut)] + /// The owner of the program. Must sign the transaction, and pays for the account rent. + pub owner: Signer<'info>, + + // The `config` account will be created (initialized) by this instruction. + // The `init` attribute indicates that this account should be created (allocated and assigned) + // and initialized with the given seeds, bump, and space. + // + // The `payer = owner` parameter means the `owner` account pays for the rent and creation cost + // of this account. + // + // `seeds = [Config::SEED_PREFIX]` sets the PDA (program-derived address) seed that + // uniquely identifies the `config` account. The `bump` is used to find a valid PDA + // that isn't already taken. + // + // `space = Config::MAXIMUM_SIZE` sets the account size so that the Solana runtime + // allocates the right amount of space in the ledger for this account's data. + #[account( + init, + payer = owner, + seeds = [Config::SEED_PREFIX], + bump, + space = Config::MAXIMUM_SIZE, + )] + /// The `config` account that stores program data needed for other instructions. + /// It is created on initialization, ensuring that all subsequent operations + /// have a consistent place to store relevant configuration information. + pub config: Account<'info, Config>, + + // The `system_program` is the program that is responsible for creating and + // allocating accounts. It is necessary whenever new accounts need to be + // created and funded. + /// The standard system program, required here to create and fund the `config` account. + pub system_program: Program<'info, System>, +} diff --git a/packages/solana/programs/snapshotter/src/contexts/mod.rs b/packages/solana/programs/snapshotter/src/contexts/mod.rs new file mode 100644 index 00000000..2f37285a --- /dev/null +++ b/packages/solana/programs/snapshotter/src/contexts/mod.rs @@ -0,0 +1,7 @@ +pub mod calculate_root; +pub mod initialize; +pub mod subscribe; + +pub use calculate_root::*; +pub use initialize::*; +pub use subscribe::*; diff --git a/packages/solana/programs/snapshotter/src/contexts/subscribe.rs b/packages/solana/programs/snapshotter/src/contexts/subscribe.rs new file mode 100644 index 00000000..50efbcdb --- /dev/null +++ b/packages/solana/programs/snapshotter/src/contexts/subscribe.rs @@ -0,0 +1,21 @@ +use crate::*; + +#[derive(Accounts)] +pub struct Subscribe<'info> { + // The `config` account represents a piece of the program's state, previously initialized and stored on-chain. + // By including `seeds = [Config::SEED_PREFIX]` and `bump`, this indicates that the `config` account's + // public key is derived using a Program-Derived Address (PDA) approach. The `bump` is an auto-calculated + // value that ensures the generated PDA does not collide with an existing account. + // + // The `mut` keyword means that this account will be modified during the execution of the instruction. + // Common modifications may include incrementing counters, logging subscription events, or updating other + // relevant fields that track user subscriptions. + #[account( + seeds = [Config::SEED_PREFIX], + bump, + mut + )] + /// The `config` account that holds data relevant to the subscription logic. This + /// account is expected to be pre-initialized and possibly managed by earlier steps in the program. + pub config: Account<'info, Config>, +} diff --git a/packages/solana/programs/snapshotter/src/error.rs b/packages/solana/programs/snapshotter/src/error.rs new file mode 100644 index 00000000..625e737b --- /dev/null +++ b/packages/solana/programs/snapshotter/src/error.rs @@ -0,0 +1,21 @@ +use anchor_lang::prelude::*; + +#[error_code] +/// Errors relevant to this program's malfunction. +pub enum ErrorCode { + #[msg("AccountAlreadySubscribed")] + /// An account is already subscribed + AccountAlreadySubscribed, + + #[msg("InvalidRemainingAccountsLength")] + /// Invalid remaining accounts length + InvalidRemainingAccountsLength, + + #[msg("InvalidSubscribedAccount")] + /// Invalid subscribed account + InvalidSubscribedAccount, + + #[msg("InvalidBatch")] + /// Invalid batch + InvalidBatch, +} diff --git a/packages/solana/programs/snapshotter/src/lib.rs b/packages/solana/programs/snapshotter/src/lib.rs new file mode 100644 index 00000000..7ea72bd9 --- /dev/null +++ b/packages/solana/programs/snapshotter/src/lib.rs @@ -0,0 +1,175 @@ +use anchor_lang::prelude::*; +use anchor_lang::solana_program::keccak::{hashv, Hash}; + +declare_id!("37298hWBczA1od9ytwgSYyhP42WLNiXieAVCxBxAeX9S"); + +pub mod contexts; +pub mod error; +pub mod state; + +pub use contexts::*; +pub use error::ErrorCode; +pub use state::*; + +pub fn account_hasher( + pubkey: &Pubkey, + lamports: u64, + data: &[u8], + owner: &Pubkey, + rent_epoch: u64, +) -> Hash { + hashv(&[ + pubkey.as_ref(), + &lamports.to_le_bytes(), + data, + owner.as_ref(), + &rent_epoch.to_le_bytes(), + ]) +} + +#[program] +pub mod snapshotter { + use super::*; + + // Determines how many accounts are processed per batch during root calculation. + pub const BATCH_SIZE: usize = 10; + + // Initializes the `Config` account when the program is first set up. + // Sets the root to a default value, marks it as not finalized, and + // sets the expected batch to zero, preparing the system for future operations. + pub fn initialize(ctx: Context) -> Result<()> { + let config = &mut ctx.accounts.config; + + config.root = Hash::default().to_bytes(); + config.root_finalized = false; + config.expected_batch = 0; + + Ok(()) + } + + // Subscribes a new account to the `subscribed_accounts` list within the `Config`. + // This function ensures that the account is not already subscribed before adding it. + pub fn subscribe(ctx: Context, account_to_subscribe: Pubkey) -> Result<()> { + let config = &mut ctx.accounts.config; + + if config.subscribed_accounts.contains(&account_to_subscribe) { + return Err(error!(ErrorCode::AccountAlreadySubscribed)); + } + + config.subscribed_accounts.push(account_to_subscribe); + + Ok(()) + } + + // Calculates the Merkle root incrementally in batches. + // + // The `batch` parameter indicates which batch of accounts we are currently processing. + // Each batch should process exactly `BATCH_SIZE` accounts (except possibly the last batch + // if the total number of subscribed accounts is not a multiple of `BATCH_SIZE`). + // + // Steps: + // 1. Verify that the batch provided matches the `expected_batch` in the `Config`. + // 2. Ensure that the provided `remaining_accounts` length matches `BATCH_SIZE` for all + // but the last batch. For the last batch, it can be fewer accounts. + // 3. If it's the last batch, finalize the root and reset `expected_batch` to 0; + // otherwise, increment `expected_batch` and mark the root as not finalized. + // 4. Hash each account's state and update the Merkle Mountain Range (MMR) root. + // 5. Store the updated root in the `config`. + pub fn calculate_root(ctx: Context, batch: u64) -> Result<()> { + let config = &mut ctx.accounts.config; + + if batch != config.expected_batch { + return Err(error!(ErrorCode::InvalidBatch)); + } + + let is_last_batch = ((config.subscribed_accounts.len() / BATCH_SIZE) as u64) == batch; + if (is_last_batch && ctx.remaining_accounts.len() > BATCH_SIZE) + || (!is_last_batch && ctx.remaining_accounts.len() != BATCH_SIZE) + { + return Err(error!(ErrorCode::InvalidRemainingAccountsLength)); + } + + if is_last_batch { + config.root_finalized = true; + config.expected_batch = 0; + } else { + config.root_finalized = false; + config.expected_batch += 1; + } + + let mut account_hashes = Vec::new(); + let start_index: usize = (batch * BATCH_SIZE as u64).try_into().unwrap(); + + for (index, account) in ctx.remaining_accounts.iter().enumerate() { + if *account.key != config.subscribed_accounts[start_index + index] { + return Err(error!(ErrorCode::InvalidSubscribedAccount)); + } + + let lamport_ref = account.lamports.borrow(); + let data_ref = account.data.borrow(); + + account_hashes.push(account_hasher( + &account.key, + **lamport_ref, + &data_ref, + account.owner, + account.rent_epoch, + )); + } + + let mut mmr = MerkleMountainRange::from(Hash::new_from_array(config.root)); + mmr.update_root(account_hashes)?; + config.root = mmr.root.to_bytes(); + + Ok(()) + } +} + +pub struct MerkleMountainRange { + pub root: Hash, +} + +impl From for MerkleMountainRange { + fn from(root: Hash) -> Self { + MerkleMountainRange { root: root } + } +} + +impl MerkleMountainRange { + pub fn new() -> Self { + MerkleMountainRange { + root: Hash::default(), + } + } + + pub fn update_root(&mut self, new_leaves: Vec) -> Result<()> { + let mut current_layer = new_leaves; + + while current_layer.len() > 1 { + let mut next_layer = Vec::new(); + let mut i = 0; + while i < current_layer.len() { + if i + 1 < current_layer.len() { + next_layer.push(hashv(&[ + ¤t_layer[i].to_bytes(), + ¤t_layer[i + 1].to_bytes(), + ])); + i += 2; + } else { + // If there's an odd one out, it becomes a peak as-is + next_layer.push(current_layer[i]); + i += 1; + } + } + current_layer = next_layer; + } + + self.root = if self.root == Hash::default() { + current_layer[0] + } else { + hashv(&[&self.root.to_bytes(), ¤t_layer[0].to_bytes()]) + }; + + Ok(()) + } +} diff --git a/packages/solana/programs/snapshotter/src/state/config.rs b/packages/solana/programs/snapshotter/src/state/config.rs new file mode 100644 index 00000000..79457448 --- /dev/null +++ b/packages/solana/programs/snapshotter/src/state/config.rs @@ -0,0 +1,53 @@ +use crate::*; + +#[account] +#[derive(Default)] +pub struct Config { + // A list of Pubkeys (addresses) that are considered to be subscribed + // to something within the context of this program (e.g., updates, notifications, etc.). + pub subscribed_accounts: Vec, + + // A 32-byte value representing some form of root data. This could be, for example, a Merkle root + // used to verify the integrity of a dataset or something similar that needs to be referenced + // persistently across multiple instructions. + pub root: [u8; 32], + + // A boolean flag indicating whether the `root` is finalized. If `true`, it might mean + // no further changes to the `root` are allowed, or that some condition has been met. + pub root_finalized: bool, + + // An unsigned 64-bit integer that might represent an expected batch number or + // counter for a process that runs periodically or sequentially. + pub expected_batch: u64, +} + +// `impl Config` block provides associated functions for `Config`. +impl Config { + // MAXIMUM_SIZE provides a static size allocation for this account’s storage. + // Anchor requires specifying account size, and this constant ensures that the + // account is allocated enough space for the data it holds. + // + // Explanation of each term: + // - 8 bytes for the account discriminator (Anchor uses an 8-byte prefix to identify account types) + // - 4 bytes for the `subscribed_accounts` vector's length (since the vector is variable-length, + // its length is stored as a 32-bit integer) + // - (32 * 256) bytes for the maximum number of `Pubkey`s we anticipate storing. Each `Pubkey` is 32 bytes, + // and we’re currently limiting ourselves to 256 of them. + // - 32 bytes for the `root` array + // - 1 byte for the boolean `root_finalized` + // - 8 bytes for the `expected_batch` (u64) + // + // In the future, if we need to store more than 256 `Pubkey`s, we might consider + // reallocation (using `realloc` in Anchor) or a PDA-based approach to store additional data. + pub const MAXIMUM_SIZE: usize = 8 // discriminator + + 4 // subscribed_accounts vec length + + (32 * 256) // max subscribed_accounts data + + 32 // root + + 1 // root_finalized + + 8; // expected_batch + + // The seed prefix is a static byte array used as part of the seeds to derive + // the program's `Config` account's PDA (Program-Derived Address). + // Using a well-known, stable prefix ensures that we can reliably find the `Config` PDA. + pub const SEED_PREFIX: &'static [u8; 6] = b"config"; +} diff --git a/packages/solana/programs/snapshotter/src/state/mod.rs b/packages/solana/programs/snapshotter/src/state/mod.rs new file mode 100644 index 00000000..a9217b9c --- /dev/null +++ b/packages/solana/programs/snapshotter/src/state/mod.rs @@ -0,0 +1,3 @@ +pub mod config; + +pub use config::*; diff --git a/packages/solana/tests/snapshotter.ts b/packages/solana/tests/snapshotter.ts new file mode 100644 index 00000000..eefc3b64 --- /dev/null +++ b/packages/solana/tests/snapshotter.ts @@ -0,0 +1,178 @@ +import * as anchor from "@coral-xyz/anchor" +import { Program } from "@coral-xyz/anchor" +import { PublicKey } from "@solana/web3.js" +import { SYSTEM_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/native/system" +import { expect } from "chai" + +import { AccountsStorage } from "../target/types/snapshotter" +import { Adapter } from "../target/types/adapter" + +const getFakeAccounts = (_length: number, _programId: PublicKey, _salt: string) => + [...Array(_length).keys()] + .map((_, _index) => + PublicKey.findProgramAddressSync([Buffer.from(_salt, "utf-8"), Buffer.from(_index.toString())], _programId), + ) + .map(([publicKey]) => publicKey) + + +describe("snapshotter", () => { + const provider = anchor.AnchorProvider.env() + anchor.setProvider(provider) + + const snapshotter = anchor.workspace.AccountsStorage as Program + const mockProgram = anchor.workspace.Adapter as Program + + describe("initialize", () => { + it("should setup the program", async () => { + const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId) + await snapshotter.methods + .initialize() + .accounts({ + owner: provider.publicKey, + config: configKey, + systemProgram: SYSTEM_PROGRAM_ID, + } as any) + .rpc() + const configData = await snapshotter.account.config.fetch(configKey) + expect(configData.subscribedAccounts.length).to.be.eq(0) + }) + }) + + describe("subscribe", () => { + it("should subscribe an account", async () => { + const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId) + + await snapshotter.methods + .subscribe(mockProgram.programId) + .accounts({ + config: configKey, + } as any) + .rpc() + + const configData = await snapshotter.account.config.fetch(configKey) + expect(configData.subscribedAccounts.length).to.be.eq(1) + expect(configData.subscribedAccounts[0].toString()).to.be.eq(mockProgram.programId.toString()) + }) + + it("should not subscribe the same account twice", async () => { + const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId) + try { + await snapshotter.methods + .subscribe(mockProgram.programId) + .accounts({ + config: configKey, + } as any) + .rpc() + } catch (_err) { + expect(_err.error.errorCode.code).to.be.eq("AccountAlreadySubscribed") + } + }) + }) + + describe("calculate_root", () => { + it("should calculate the root with 1 batch (5)", async () => { + const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId) + + const fakeAccounts = getFakeAccounts(4, snapshotter.programId, "fake1") + for (const fakeAccount of fakeAccounts) { + await snapshotter.methods + .subscribe(fakeAccount) + .accounts({ + config: configKey, + } as any) + .rpc() + } + + const fakeAccountsRemainingAccounts = fakeAccounts.map((_fakeAccount) => ({ + isSigner: false, + isWritable: false, + pubkey: _fakeAccount, + })) + + await snapshotter.methods + .calculateRoot(new anchor.BN(0)) + .accounts({ + config: configKey, + } as any) + .remainingAccounts([ + { + isSigner: false, + isWritable: false, + pubkey: mockProgram.programId, + }, + ...fakeAccountsRemainingAccounts, + ]) + .rpc() + + let configData = await snapshotter.account.config.fetch(configKey) + expect(configData.rootFinalized).to.be.eq(true) + expect(configData.expectedBatch.toNumber()).to.be.eq(0) + }) + + it("should calculate the root with 3 batches (10 + 10 + 1)", async () => { + const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId) + + const alreadySubscribedFakeAccounts = getFakeAccounts(4, snapshotter.programId, "fake1") + const newFakeAccounts = getFakeAccounts(16, snapshotter.programId, "fake2") + for (const fakeAccount of newFakeAccounts) { + await snapshotter.methods + .subscribe(fakeAccount) + .accounts({ + config: configKey, + } as any) + .rpc() + } + + const fakeAccountsRemainingAccounts = [...alreadySubscribedFakeAccounts, ...newFakeAccounts].map( + (_fakeAccount) => ({ + isSigner: false, + isWritable: false, + pubkey: _fakeAccount, + }), + ) + + await snapshotter.methods + .calculateRoot(new anchor.BN(0)) + .accounts({ + config: configKey, + } as any) + .remainingAccounts([ + { + isSigner: false, + isWritable: false, + pubkey: mockProgram.programId, + }, + ...fakeAccountsRemainingAccounts.slice(0, 9), + ]) + .rpc() + + let configData = await snapshotter.account.config.fetch(configKey) + expect(configData.rootFinalized).to.be.eq(false) + expect(configData.expectedBatch.toNumber()).to.be.eq(1) + + await snapshotter.methods + .calculateRoot(new anchor.BN(1)) + .accounts({ + config: configKey, + } as any) + .remainingAccounts([...fakeAccountsRemainingAccounts.slice(9, 19)]) + .rpc() + + configData = await snapshotter.account.config.fetch(configKey) + expect(configData.rootFinalized).to.be.eq(false) + expect(configData.expectedBatch.toNumber()).to.be.eq(2) + + await snapshotter.methods + .calculateRoot(new anchor.BN(2)) + .accounts({ + config: configKey, + } as any) + .remainingAccounts([...fakeAccountsRemainingAccounts.slice(19, 20)]) + .rpc() + + configData = await snapshotter.account.config.fetch(configKey) + expect(configData.rootFinalized).to.be.eq(true) + expect(configData.expectedBatch.toNumber()).to.be.eq(0) + }) + }) +}) From ed82a66ec7db2de8279abcab62eadd575bcb8bdc Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Tue, 17 Dec 2024 17:28:08 +0100 Subject: [PATCH 17/31] refactor(solana): rm not used wormhole_reporter errors --- .../programs/wormhole-reporter/src/error.rs | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/packages/solana/programs/wormhole-reporter/src/error.rs b/packages/solana/programs/wormhole-reporter/src/error.rs index 16a309ea..7d8ebb01 100644 --- a/packages/solana/programs/wormhole-reporter/src/error.rs +++ b/packages/solana/programs/wormhole-reporter/src/error.rs @@ -11,10 +11,6 @@ pub enum ErrorCode { /// Specified Wormhole fee collector PDA is wrong. InvalidWormholeFeeCollector, - #[msg("InvalidWormholeEmitter")] - /// Specified program's emitter PDA is wrong. - InvalidWormholeEmitter, - #[msg("InvalidWormholeSequence")] /// Specified emitter's sequence PDA is wrong. InvalidWormholeSequence, @@ -22,20 +18,4 @@ pub enum ErrorCode { #[msg("InvalidSysvar")] /// Specified sysvar is wrong. InvalidSysvar, - - #[msg("OwnerOnly")] - /// Only the program's owner is permitted. - OwnerOnly, - - #[msg("InvalidForeignEmitter")] - /// Specified foreign emitter has a bad chain ID or zero address. - InvalidForeignEmitter, - - #[msg("BumpNotFound")] - /// Bump not found in `bumps` map. - BumpNotFound, - - #[msg("InvalidMessage")] - /// Deserialized message has unexpected payload type. - InvalidMessage, } From bb7e50a1f358d63ad1c6da30f308e807903a1181 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Tue, 17 Dec 2024 18:18:59 +0100 Subject: [PATCH 18/31] feat(solana): adds nonce to snapshotter --- packages/solana/programs/snapshotter/src/lib.rs | 2 ++ packages/solana/programs/snapshotter/src/state/config.rs | 6 +++++- packages/solana/tests/snapshotter.ts | 7 ++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/solana/programs/snapshotter/src/lib.rs b/packages/solana/programs/snapshotter/src/lib.rs index 7ea72bd9..e16b5b6f 100644 --- a/packages/solana/programs/snapshotter/src/lib.rs +++ b/packages/solana/programs/snapshotter/src/lib.rs @@ -43,6 +43,7 @@ pub mod snapshotter { config.root = Hash::default().to_bytes(); config.root_finalized = false; config.expected_batch = 0; + config.nonce = 0; Ok(()) } @@ -92,6 +93,7 @@ pub mod snapshotter { if is_last_batch { config.root_finalized = true; config.expected_batch = 0; + config.nonce += 1; } else { config.root_finalized = false; config.expected_batch += 1; diff --git a/packages/solana/programs/snapshotter/src/state/config.rs b/packages/solana/programs/snapshotter/src/state/config.rs index 79457448..732f2bfb 100644 --- a/packages/solana/programs/snapshotter/src/state/config.rs +++ b/packages/solana/programs/snapshotter/src/state/config.rs @@ -19,6 +19,9 @@ pub struct Config { // An unsigned 64-bit integer that might represent an expected batch number or // counter for a process that runs periodically or sequentially. pub expected_batch: u64, + + // An unsigned 64-bit integer that represent the number of calculated roots + pub nonce: u64, } // `impl Config` block provides associated functions for `Config`. @@ -44,7 +47,8 @@ impl Config { + (32 * 256) // max subscribed_accounts data + 32 // root + 1 // root_finalized - + 8; // expected_batch + + 8 // expected_batch + + 8; // nonce // The seed prefix is a static byte array used as part of the seeds to derive // the program's `Config` account's PDA (Program-Derived Address). diff --git a/packages/solana/tests/snapshotter.ts b/packages/solana/tests/snapshotter.ts index eefc3b64..a131605d 100644 --- a/packages/solana/tests/snapshotter.ts +++ b/packages/solana/tests/snapshotter.ts @@ -4,7 +4,7 @@ import { PublicKey } from "@solana/web3.js" import { SYSTEM_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/native/system" import { expect } from "chai" -import { AccountsStorage } from "../target/types/snapshotter" +import { Snapshotter } from "../target/types/snapshotter" import { Adapter } from "../target/types/adapter" const getFakeAccounts = (_length: number, _programId: PublicKey, _salt: string) => @@ -14,12 +14,11 @@ const getFakeAccounts = (_length: number, _programId: PublicKey, _salt: string) ) .map(([publicKey]) => publicKey) - describe("snapshotter", () => { const provider = anchor.AnchorProvider.env() anchor.setProvider(provider) - const snapshotter = anchor.workspace.AccountsStorage as Program + const snapshotter = anchor.workspace.Snapshotter as Program const mockProgram = anchor.workspace.Adapter as Program describe("initialize", () => { @@ -107,6 +106,7 @@ describe("snapshotter", () => { let configData = await snapshotter.account.config.fetch(configKey) expect(configData.rootFinalized).to.be.eq(true) expect(configData.expectedBatch.toNumber()).to.be.eq(0) + expect(configData.nonce.toNumber()).to.be.eq(1) }) it("should calculate the root with 3 batches (10 + 10 + 1)", async () => { @@ -173,6 +173,7 @@ describe("snapshotter", () => { configData = await snapshotter.account.config.fetch(configKey) expect(configData.rootFinalized).to.be.eq(true) expect(configData.expectedBatch.toNumber()).to.be.eq(0) + expect(configData.nonce.toNumber()).to.be.eq(2) }) }) }) From 6798baa885de170332b608e9d1b0ab29785e072a Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 18 Dec 2024 06:31:13 +0100 Subject: [PATCH 19/31] refactor(solana): rm dispatch_slot in favour of dispatch_root within wormhole_reporter --- packages/solana/Cargo.lock | 2 +- .../programs/wormhole-reporter/Cargo.toml | 2 +- .../{dispatch_slot.rs => dispatch_root.rs} | 14 ++- .../src/contexts/initialize.rs | 8 +- .../wormhole-reporter/src/contexts/mod.rs | 4 +- .../programs/wormhole-reporter/src/error.rs | 8 ++ .../programs/wormhole-reporter/src/lib.rs | 79 +++++++------ .../wormhole-reporter/src/state/config.rs | 3 + packages/solana/tests/utils.ts | 9 ++ packages/solana/tests/wormhole-reporter.ts | 104 ++++++++++++------ 10 files changed, 156 insertions(+), 77 deletions(-) rename packages/solana/programs/wormhole-reporter/src/contexts/{dispatch_slot.rs => dispatch_root.rs} (90%) diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index 0602dfe9..10f6c66d 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -3656,7 +3656,7 @@ version = "0.1.0" dependencies = [ "anchor-lang", "message", - "slots", + "snapshotter", "wormhole-anchor-sdk", "wormhole-io", ] diff --git a/packages/solana/programs/wormhole-reporter/Cargo.toml b/packages/solana/programs/wormhole-reporter/Cargo.toml index 3059ceda..50b82dd6 100644 --- a/packages/solana/programs/wormhole-reporter/Cargo.toml +++ b/packages/solana/programs/wormhole-reporter/Cargo.toml @@ -21,7 +21,7 @@ idl-build = ["anchor-lang/idl-build", "wormhole-anchor-sdk/idl-build"] [dependencies] anchor-lang = "0.30.1" -slots = { path = "../../shared/slots" } message = { path = "../../shared/message" } wormhole-anchor-sdk = { version = "0.30.1-alpha.3", default-features = false } wormhole-io = "0.1.3" +snapshotter = { path = "../snapshotter", default-features = false, features = ["cpi"] } \ No newline at end of file diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_slot.rs b/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_root.rs similarity index 90% rename from packages/solana/programs/wormhole-reporter/src/contexts/dispatch_slot.rs rename to packages/solana/programs/wormhole-reporter/src/contexts/dispatch_root.rs index 3a98ef51..4422c76a 100644 --- a/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_slot.rs +++ b/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_root.rs @@ -1,5 +1,4 @@ use anchor_lang::prelude::*; -use anchor_lang::solana_program::sysvar; use wormhole_anchor_sdk::wormhole::{self, program::Wormhole}; use crate::{ @@ -11,7 +10,7 @@ use crate::{ const SEED_PREFIX_SENT: &[u8; 4] = b"sent"; #[derive(Accounts)] -pub struct DispatchSlot<'info> { +pub struct DispatchRoot<'info> { #[account(mut)] /// Payer will pay Wormhole fee to post a message. pub payer: Signer<'info>, @@ -70,6 +69,13 @@ pub struct DispatchSlot<'info> { /// account be mutable. pub wormhole_message: UncheckedAccount<'info>, + /// CHECK: Snapshotter program + #[account( + mut, + address = config.snapshotter_config @ ErrorCode::InvalidSnapshotterConfig + )] + pub snapshotter_config: UncheckedAccount<'info>, + /// System program. pub system_program: Program<'info, System>, @@ -78,8 +84,4 @@ pub struct DispatchSlot<'info> { /// Rent sysvar. pub rent: Sysvar<'info, Rent>, - - /// CHECK: We are reading from SlotHashes sysvar the latest slot hash - #[account(address = sysvar::slot_hashes::ID)] - pub slot_hashes: AccountInfo<'info>, } diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs index 48d27e3b..2a6b3763 100644 --- a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs +++ b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs @@ -1,5 +1,4 @@ use anchor_lang::prelude::*; -use anchor_lang::solana_program::sysvar; use wormhole_anchor_sdk::wormhole::{self, program::Wormhole}; use crate::state::{Config, WormholeEmitter}; @@ -93,6 +92,9 @@ pub struct Initialize<'info> { /// [`wormhole::post_message`] requires this account be mutable. pub wormhole_message: UncheckedAccount<'info>, + /// CHECK: Snapshotter program + pub snapshotter_config: UncheckedAccount<'info>, + /// Clock sysvar. pub clock: Sysvar<'info, Clock>, @@ -101,8 +103,4 @@ pub struct Initialize<'info> { /// System program. pub system_program: Program<'info, System>, - - /// CHECK: We are reading from SlotHashes sysvar the latest slot hash - #[account(address = sysvar::slot_hashes::ID)] - pub slot_hashes: AccountInfo<'info>, } diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/mod.rs b/packages/solana/programs/wormhole-reporter/src/contexts/mod.rs index 24945d67..c8092b30 100644 --- a/packages/solana/programs/wormhole-reporter/src/contexts/mod.rs +++ b/packages/solana/programs/wormhole-reporter/src/contexts/mod.rs @@ -1,5 +1,5 @@ -pub mod dispatch_slot; +pub mod dispatch_root; pub mod initialize; -pub use dispatch_slot::*; +pub use dispatch_root::*; pub use initialize::*; diff --git a/packages/solana/programs/wormhole-reporter/src/error.rs b/packages/solana/programs/wormhole-reporter/src/error.rs index 7d8ebb01..2bb3398c 100644 --- a/packages/solana/programs/wormhole-reporter/src/error.rs +++ b/packages/solana/programs/wormhole-reporter/src/error.rs @@ -18,4 +18,12 @@ pub enum ErrorCode { #[msg("InvalidSysvar")] /// Specified sysvar is wrong. InvalidSysvar, + + #[msg("RootNotFinalized")] + /// Snapshotter root not finalized + RootNotFinalized, + + #[msg("InvalidSnapshotterConfig")] + /// Invalid Snapshotter config + InvalidSnapshotterConfig, } diff --git a/packages/solana/programs/wormhole-reporter/src/lib.rs b/packages/solana/programs/wormhole-reporter/src/lib.rs index 6722a234..47c1c1a8 100644 --- a/packages/solana/programs/wormhole-reporter/src/lib.rs +++ b/packages/solana/programs/wormhole-reporter/src/lib.rs @@ -8,30 +8,38 @@ pub use contexts::*; pub use error::ErrorCode; pub use state::*; -declare_id!("AeUyN4y9cvEzCDTVUy3ZPhrYw7i44kNBsqMeGysZfWid"); +declare_id!("48Vq4rpj7tiZKvpVkzmR5kHUTLy6KdL1c4zkFw17cNZw"); #[program] pub mod wormhole_reporter { use super::*; use anchor_lang::solana_program; use message::Message; - use slots::get_slot; + use snapshotter::state::Config as SnapshotterConfig; use wormhole_anchor_sdk::wormhole; - /// This instruction initializes the program config, which is meant - /// to store data useful for other instructions. The config specifies - /// an owner (e.g. multisig) and should be read-only for every instruction. + /// Initializes the Wormhole Reporter program. + /// + /// This function sets up the initial configuration, initializes the Wormhole emitter, + /// handles any necessary fee transfers, and posts an initial message to Wormhole to + /// establish a SequenceTracker account. /// /// # Arguments /// - /// * `ctx` - `Initialize` contexts - pub fn initialize(ctx: Context, slot_number: u64) -> Result<()> { + /// * `ctx` - The context containing all the accounts required for initialization. + /// + /// # Returns + /// + /// * `Result<()>` - Returns `Ok(())` if successful, or an error otherwise. + pub fn initialize(ctx: Context) -> Result<()> { let config = &mut ctx.accounts.config; - // Set the owner of the config (effectively the owner of the program). + // Set the owner of the configuration to the provided owner account config.owner = ctx.accounts.owner.key(); - // Set Wormhole related addresses. + // Set the snapshotter configuration account + config.snapshotter_config = ctx.accounts.snapshotter_config.key(); + { let wormhole = &mut config.wormhole; @@ -48,7 +56,6 @@ pub mod wormhole_reporter { } // Set default values for posting Wormhole messages. - // // Zero means no batching. config.batch_id = 0; @@ -102,11 +109,27 @@ pub mod wormhole_reporter { // use the PDA to access and deserialize the message data. // // we use method #2. + + // Prepare to post an initial message to Wormhole during initialization + // This allows Wormhole to create a SequenceTracker account for the emitter + // which will be used to track message sequences in subsequent operations + + // References to the Wormhole emitter and the main config let wormhole_emitter = &ctx.accounts.wormhole_emitter; let config = &ctx.accounts.config; - let slot_hash = get_slot(&ctx.accounts.slot_hashes, slot_number)?; - let message = Message::from((slot_number, slot_hash)); + // Deserialize the snapshotter configuration data + let mut data_slice: &[u8] = &ctx.accounts.snapshotter_config.data.borrow(); + let snapshotter_config: SnapshotterConfig = + AccountDeserialize::try_deserialize(&mut data_slice)?; + + // Ensure that the root is finalized before proceeding + if !snapshotter_config.root_finalized { + return Err(error!(ErrorCode::RootNotFinalized)); + } + + // Create a Wormhole message from the snapshotter's nonce and root + let message = Message::from((snapshotter_config.nonce, snapshotter_config.root)); let mut payload: Vec = Vec::new(); message.serialize(&mut payload)?; @@ -142,30 +165,19 @@ pub mod wormhole_reporter { Ok(()) } - /// Dispatches a Wormhole message for a specific slot. + /// Dispatches a root by posting a message to Wormhole. /// - /// This function handles the necessary steps to post a message to the Wormhole bridge, - /// including paying the required fee (if any), preparing the message payload, and invoking - /// the `wormhole::post_message` CPI. It uses Program Derived Addresses (PDAs) to manage - /// the Wormhole emitter and message accounts securely and reliably. + /// This function handles fee transfers if required and posts a new message to Wormhole + /// containing the latest snapshotter root and nonce. /// /// # Arguments /// - /// - `ctx`: A `Context` object containing all necessary accounts and data required for the dispatch process. - /// - `slot_number`: The slot number for which the message is being dispatched. This is used to - /// retrieve the slot hash and include it in the payload. - /// - /// # Notes - /// - /// - The function uses a PDA to manage the Wormhole message account, allowing the program - /// to retain access to and deserialize the message data as needed. - /// - The Wormhole emitter and sequence accounts are derived and managed by this program. - /// - The finality of the message is determined by the configuration stored in the `config` account. + /// * `ctx` - The context containing all the accounts required for dispatching the root. /// /// # Returns /// - /// This function returns `Ok(())` on success or a relevant error if the process fails. - pub fn dispatch_slot(ctx: Context, slot_number: u64) -> Result<()> { + /// * `Result<()>` - Returns `Ok(())` if successful, or an error otherwise. + pub fn dispatch_root(ctx: Context) -> Result<()> { // If Wormhole requires a fee before posting a message, we need to // transfer lamports to the fee collector. Otherwise // `wormhole::post_message` will fail. @@ -203,8 +215,13 @@ pub mod wormhole_reporter { let wormhole_emitter = &ctx.accounts.wormhole_emitter; let config = &ctx.accounts.config; - let slot_hash = get_slot(&ctx.accounts.slot_hashes, slot_number)?; - let message = Message::from((slot_number, slot_hash)); + let mut data_slice: &[u8] = &ctx.accounts.snapshotter_config.data.borrow(); + let snapshotter_config: SnapshotterConfig = + AccountDeserialize::try_deserialize(&mut data_slice)?; + if !snapshotter_config.root_finalized { + return Err(error!(ErrorCode::RootNotFinalized)); + } + let message = Message::from((snapshotter_config.nonce, snapshotter_config.root)); let mut payload: Vec = Vec::new(); message.serialize(&mut payload)?; diff --git a/packages/solana/programs/wormhole-reporter/src/state/config.rs b/packages/solana/programs/wormhole-reporter/src/state/config.rs index cd22a1df..2e4df0bb 100644 --- a/packages/solana/programs/wormhole-reporter/src/state/config.rs +++ b/packages/solana/programs/wormhole-reporter/src/state/config.rs @@ -33,6 +33,8 @@ pub struct Config { /// AKA consistency level. u8 representation of Solana's /// [Finality](wormhole_anchor_sdk::wormhole::Finality). pub finality: u8, + /// Snapshotter config address. + pub snapshotter_config: Pubkey } impl Config { @@ -41,6 +43,7 @@ impl Config { + WormholeAddresses::LEN + 4 // batch_id + 1 // finality + + 32 // snapshotter_config ; /// AKA `b"config"`. diff --git a/packages/solana/tests/utils.ts b/packages/solana/tests/utils.ts index fdd6d70e..cd9e3cf9 100644 --- a/packages/solana/tests/utils.ts +++ b/packages/solana/tests/utils.ts @@ -1 +1,10 @@ +import { PublicKey } from "@solana/web3.js" + export const intToBytes32Buff = (_num: number) => Buffer.from(_num.toString(16).padStart(64, "0"), "hex") + +export const getFakeAccounts = (_length: number, _programId: PublicKey, _salt: string) => + [...Array(_length).keys()] + .map((_, _index) => + PublicKey.findProgramAddressSync([Buffer.from(_salt, "utf-8"), Buffer.from(_index.toString())], _programId), + ) + .map(([publicKey]) => publicKey) diff --git a/packages/solana/tests/wormhole-reporter.ts b/packages/solana/tests/wormhole-reporter.ts index 4dd94e64..159dbaee 100644 --- a/packages/solana/tests/wormhole-reporter.ts +++ b/packages/solana/tests/wormhole-reporter.ts @@ -1,6 +1,6 @@ import * as anchor from "@coral-xyz/anchor" import { expect } from "chai" -import { Keypair, LAMPORTS_PER_SOL, PublicKey, PublicKeyInitData, SYSVAR_SLOT_HASHES_PUBKEY } from "@solana/web3.js" +import { PublicKey, PublicKeyInitData } from "@solana/web3.js" import { deriveAddress, getPostMessageCpiAccounts, @@ -10,10 +10,13 @@ import { getPostedMessage, getProgramSequenceTracker } from "@certusone/wormhole import { CONTRACTS } from "@certusone/wormhole-sdk" import { Program } from "@coral-xyz/anchor" import { AbiCoder } from "ethers" +import { SYSTEM_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/native/system" import { WormholeReporter } from "../target/types/wormhole_reporter" +import { Snapshotter } from "../target/types/snapshotter" +import { getFakeAccounts } from "./utils" -const WORMHOLE_CONTRACTS = CONTRACTS.TESTNET +const WORMHOLE_CONTRACTS = CONTRACTS.MAINNET const CORE_BRIDGE_PID = new PublicKey(WORMHOLE_CONTRACTS.solana.core) export const deriveWormholeMessageKey = (_programId: PublicKeyInitData, _sequence: bigint) => { @@ -33,61 +36,103 @@ export const deriveWormholeMessageKey = (_programId: PublicKeyInitData, _sequenc describe("wormhole_reporter", () => { const provider = anchor.AnchorProvider.local() anchor.setProvider(provider) - const payer = new Keypair() const reporter = anchor.workspace.WormholeReporter as Program + const snapshotter = anchor.workspace.Snapshotter as Program before(async () => { - await provider.connection.confirmTransaction( - await provider.connection.requestAirdrop(payer.publicKey, 1000 * LAMPORTS_PER_SOL), - ) + const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId) + await snapshotter.methods + .initialize() + .accounts({ + owner: provider.publicKey, + config: configKey, + systemProgram: SYSTEM_PROGRAM_ID, + } as any) + .rpc() + + const fakeAccounts = getFakeAccounts(4, snapshotter.programId, "fake11") + for (const fakeAccount of fakeAccounts) { + await snapshotter.methods + .subscribe(fakeAccount) + .accounts({ + config: configKey, + } as any) + .rpc() + } + + await snapshotter.methods + .calculateRoot(new anchor.BN(0)) + .accounts({ + config: configKey, + } as any) + .remainingAccounts( + fakeAccounts.map((_fakeAccount) => ({ + isSigner: false, + isWritable: false, + pubkey: _fakeAccount, + })), + ) + .rpc() }) describe("initialize", () => { it("should set up the program", async () => { - const slot = await provider.connection.getSlot() - const slotNumberToDispatch = new anchor.BN(slot - 1) - const message = deriveWormholeMessageKey(reporter.programId, 1n) - const wormholeAccounts = getPostMessageCpiAccounts(reporter.programId, CORE_BRIDGE_PID, payer.publicKey, message) + const wormholeAccounts = getPostMessageCpiAccounts( + reporter.programId, + CORE_BRIDGE_PID, + provider.publicKey, + message, + ) const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], reporter.programId) + const [snapshotterConfigkey] = PublicKey.findProgramAddressSync( + [Buffer.from("config", "utf-8")], + snapshotter.programId, + ) await reporter.methods - .initialize(slotNumberToDispatch) + .initialize() .accounts({ - owner: new PublicKey(payer.publicKey), + owner: new PublicKey(provider.publicKey), config: configKey, wormholeProgram: new PublicKey(CORE_BRIDGE_PID), - slotHashes: SYSVAR_SLOT_HASHES_PUBKEY, + snapshotterConfig: snapshotterConfigkey, ...wormholeAccounts, } as any) - .signers([payer]) .rpc() const configData = await reporter.account.config.fetch(configKey) - expect(configData.owner).deep.equals(payer.publicKey) + expect(configData.owner).deep.equals(provider.publicKey) const { wormholeBridge, wormholeFeeCollector } = getWormholeDerivedAccounts(reporter.programId, CORE_BRIDGE_PID) expect(configData.wormhole.bridge).deep.equals(wormholeBridge) expect(configData.wormhole.feeCollector).deep.equals(wormholeFeeCollector) + expect(configData.snapshotterConfig).deep.equals(snapshotterConfigkey) }) }) - describe("dispatch_slot", () => { - it("should dispatch slot", async () => { - const slot = await provider.connection.getSlot() - const slotNumberToDispatch = new anchor.BN(slot - 1) - + describe("dispatch_root", () => { + it("should dispatch a root", async () => { const tracker = await getProgramSequenceTracker(provider.connection, reporter.programId, CORE_BRIDGE_PID) const message = deriveWormholeMessageKey(reporter.programId, tracker.sequence + 1n) - const wormholeAccounts = getPostMessageCpiAccounts(reporter.programId, CORE_BRIDGE_PID, payer.publicKey, message) + const wormholeAccounts = getPostMessageCpiAccounts( + reporter.programId, + CORE_BRIDGE_PID, + provider.publicKey, + message, + ) + const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], reporter.programId) + const [snapshotterConfigkey] = PublicKey.findProgramAddressSync( + [Buffer.from("config", "utf-8")], + snapshotter.programId, + ) await reporter.methods - .dispatchSlot(slotNumberToDispatch) + .dispatchRoot() .accounts({ - config: PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], reporter.programId), + config: configKey, wormholeProgram: new PublicKey(CORE_BRIDGE_PID), - slotHashes: SYSVAR_SLOT_HASHES_PUBKEY, + snapshotterConfig: snapshotterConfigkey, ...wormholeAccounts, } as any) - .signers([payer]) .rpc() const { payload } = ( @@ -95,12 +140,9 @@ describe("wormhole_reporter", () => { ).message const abiCoder = new AbiCoder() - const [[dispatchedSlotNumber], [dispatchedSlotHash]] = abiCoder.decode( - ["uint256[]", "bytes32[]"], - "0x" + payload.toString("hex"), - ) - expect(parseInt(dispatchedSlotNumber)).equals(slotNumberToDispatch.toNumber()) - expect(dispatchedSlotHash).to.be.not.null + const [[nonce], [root]] = abiCoder.decode(["uint256[]", "bytes32[]"], "0x" + payload.toString("hex")) + expect(parseInt(nonce)).equals(1) + expect(root).to.be.not.null }) }) }) From 54db4cbc1dabe93557a314c40684d8785528c671 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 18 Dec 2024 06:35:32 +0100 Subject: [PATCH 20/31] refactor(solana): imports getFakeAccounts from utils --- packages/solana/tests/snapshotter.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/solana/tests/snapshotter.ts b/packages/solana/tests/snapshotter.ts index a131605d..3f2efe18 100644 --- a/packages/solana/tests/snapshotter.ts +++ b/packages/solana/tests/snapshotter.ts @@ -5,21 +5,13 @@ import { SYSTEM_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/native/system" import { expect } from "chai" import { Snapshotter } from "../target/types/snapshotter" -import { Adapter } from "../target/types/adapter" - -const getFakeAccounts = (_length: number, _programId: PublicKey, _salt: string) => - [...Array(_length).keys()] - .map((_, _index) => - PublicKey.findProgramAddressSync([Buffer.from(_salt, "utf-8"), Buffer.from(_index.toString())], _programId), - ) - .map(([publicKey]) => publicKey) +import { getFakeAccounts } from "./utils" describe("snapshotter", () => { const provider = anchor.AnchorProvider.env() anchor.setProvider(provider) const snapshotter = anchor.workspace.Snapshotter as Program - const mockProgram = anchor.workspace.Adapter as Program describe("initialize", () => { it("should setup the program", async () => { @@ -41,8 +33,9 @@ describe("snapshotter", () => { it("should subscribe an account", async () => { const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId) + const [fakeAccount] = getFakeAccounts(1, snapshotter.programId, "fake0") await snapshotter.methods - .subscribe(mockProgram.programId) + .subscribe(fakeAccount) .accounts({ config: configKey, } as any) @@ -50,14 +43,15 @@ describe("snapshotter", () => { const configData = await snapshotter.account.config.fetch(configKey) expect(configData.subscribedAccounts.length).to.be.eq(1) - expect(configData.subscribedAccounts[0].toString()).to.be.eq(mockProgram.programId.toString()) + expect(configData.subscribedAccounts[0].toString()).to.be.eq(fakeAccount.toString()) }) it("should not subscribe the same account twice", async () => { const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId) try { + const [fakeAccount] = getFakeAccounts(1, snapshotter.programId, "fake0") await snapshotter.methods - .subscribe(mockProgram.programId) + .subscribe(fakeAccount) .accounts({ config: configKey, } as any) @@ -97,7 +91,7 @@ describe("snapshotter", () => { { isSigner: false, isWritable: false, - pubkey: mockProgram.programId, + pubkey: getFakeAccounts(1, snapshotter.programId, "fake0")[0], }, ...fakeAccountsRemainingAccounts, ]) @@ -140,7 +134,7 @@ describe("snapshotter", () => { { isSigner: false, isWritable: false, - pubkey: mockProgram.programId, + pubkey: getFakeAccounts(1, snapshotter.programId, "fake0")[0], }, ...fakeAccountsRemainingAccounts.slice(0, 9), ]) From 074a9b8177660c4957308f8da598d11e46fbc956 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 18 Dec 2024 06:37:59 +0100 Subject: [PATCH 21/31] refactor(solana): adds missing comments to wormhole_reporter --- packages/solana/programs/wormhole-reporter/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/solana/programs/wormhole-reporter/src/lib.rs b/packages/solana/programs/wormhole-reporter/src/lib.rs index 47c1c1a8..2ef2f467 100644 --- a/packages/solana/programs/wormhole-reporter/src/lib.rs +++ b/packages/solana/programs/wormhole-reporter/src/lib.rs @@ -215,12 +215,17 @@ pub mod wormhole_reporter { let wormhole_emitter = &ctx.accounts.wormhole_emitter; let config = &ctx.accounts.config; + // Deserialize the snapshotter configuration data let mut data_slice: &[u8] = &ctx.accounts.snapshotter_config.data.borrow(); let snapshotter_config: SnapshotterConfig = AccountDeserialize::try_deserialize(&mut data_slice)?; + + // Ensure that the root is finalized before proceeding if !snapshotter_config.root_finalized { return Err(error!(ErrorCode::RootNotFinalized)); } + + // Create a Wormhole message from the snapshotter's nonce and root let message = Message::from((snapshotter_config.nonce, snapshotter_config.root)); let mut payload: Vec = Vec::new(); message.serialize(&mut payload)?; From 3f611be779ed8181996c9cb4a50cdecda65054a4 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 18 Dec 2024 07:00:42 +0100 Subject: [PATCH 22/31] refactor(solana): refactors snapshotter comments --- .../src/contexts/calculate_root.rs | 46 ++++++++--- .../snapshotter/src/contexts/initialize.rs | 61 +++++++++------ .../snapshotter/src/contexts/subscribe.rs | 36 ++++++--- .../solana/programs/snapshotter/src/lib.rs | 53 +++++++++++-- .../programs/snapshotter/src/state/config.rs | 77 +++++++++++-------- 5 files changed, 192 insertions(+), 81 deletions(-) diff --git a/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs b/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs index 0d083ef9..73f3b8fe 100644 --- a/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs +++ b/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs @@ -2,14 +2,27 @@ use crate::*; #[derive(Accounts)] pub struct CalculateRoot<'info> { - // The `config` account will be accessed and potentially modified by this instruction. - // The `#[account(...)]` attribute macro applies constraints to this account: - // - `seeds = [Config::SEED_PREFIX]`: The account is derived from a program-derived address (PDA) - // using `Config::SEED_PREFIX` as the seed. This ensures that the correct PDA is referenced. - // - `bump`: Used in combination with the seeds to find the PDA. The `bump` ensures a valid PDA - // that is not already taken by another account. - // - `mut`: The `mut` keyword indicates that this account will be mutated (written to) - // during the instruction execution. + /// The `config` account holds the snapshotter's configuration and state. + /// + /// - **PDA Derivation**: The account is a PDA derived using the `Config::SEED_PREFIX` as the seed. This ensures + /// that the account is uniquely identified and securely accessed by the program. + /// + /// - **Bump Seed**: The `bump` attribute is used to derive the PDA alongside the seeds. It guarantees that the PDA + /// is valid and helps prevent collisions with other accounts. + /// + /// - **Mutability**: The `mut` keyword indicates that this account will be modified during the instruction execution. + /// Specifically, the `calculate_root` function updates fields within the `Config` account, such as the Merkle root, + /// finalization status, expected batch number, and nonce. + /// + /// ## Example Usage in `calculate_root` Function: + /// + /// ```rust + /// pub fn calculate_root(ctx: Context, batch: u64) -> Result<()> { + /// let config = &mut ctx.accounts.config; + /// // ... perform operations that modify `config` ... + /// } + /// ``` + /// #[account( seeds = [Config::SEED_PREFIX], bump, @@ -17,8 +30,19 @@ pub struct CalculateRoot<'info> { )] pub config: Account<'info, Config>, - // The `clock` field references the Sysvar `Clock` account, which provides the current - // cluster time, slot, epoch, etc. It is read-only and used for time-based logic within - // the instruction if necessary. + /// The `clock` Sysvar account provides access to the current cluster time, slot, epoch, etc. + /// + /// - **Purpose**: Useful for implementing time-based logic within the instruction, such as enforcing timeouts, + /// scheduling, or validating the timing of certain operations. + /// + /// - **Read-Only**: The `clock` account is read-only and cannot be modified by the program. It simply provides + /// information about the current state of the Solana cluster's timing parameters. + /// + /// ## Example Usage in `calculate_root` Function: + /// + /// ```rust + /// let current_epoch = ctx.accounts.clock.epoch; + /// ``` + /// pub clock: Sysvar<'info, Clock>, } diff --git a/packages/solana/programs/snapshotter/src/contexts/initialize.rs b/packages/solana/programs/snapshotter/src/contexts/initialize.rs index 93083f84..1237c763 100644 --- a/packages/solana/programs/snapshotter/src/contexts/initialize.rs +++ b/packages/solana/programs/snapshotter/src/contexts/initialize.rs @@ -2,28 +2,39 @@ use crate::*; #[derive(Accounts)] pub struct Initialize<'info> { - // The `owner` is a Signer account, indicating that whoever calls this instruction - // must sign the transaction with their private key. This ensures that the initializer - // has authority. - // `#[account(mut)]` is used here because the `payer` field below uses this account's - // lamports to fund the creation of the `config` account. + /// The `owner` is a Signer account, indicating that whoever calls this instruction + /// must sign the transaction with their private key. This ensures that the initializer + /// has authority. + /// + /// `#[account(mut)]` is used here because the `owner` account's lamports are used + /// to fund the creation of the `config` account. + /// + /// ## Attributes + /// + /// - **`mut`**: Marks the `owner` account as mutable, allowing its lamports to be debited. #[account(mut)] - /// The owner of the program. Must sign the transaction, and pays for the account rent. + /// The owner of the program. Must sign the transaction and pays for the account rent. pub owner: Signer<'info>, - // The `config` account will be created (initialized) by this instruction. - // The `init` attribute indicates that this account should be created (allocated and assigned) - // and initialized with the given seeds, bump, and space. - // - // The `payer = owner` parameter means the `owner` account pays for the rent and creation cost - // of this account. - // - // `seeds = [Config::SEED_PREFIX]` sets the PDA (program-derived address) seed that - // uniquely identifies the `config` account. The `bump` is used to find a valid PDA - // that isn't already taken. - // - // `space = Config::MAXIMUM_SIZE` sets the account size so that the Solana runtime - // allocates the right amount of space in the ledger for this account's data. + /// The `config` account will be created (initialized) by this instruction. + /// + /// The `init` attribute indicates that this account should be created (allocated and assigned) + /// and initialized with the given seeds, bump, and space. + /// + /// - **`payer = owner`**: The `owner` account pays for the rent and creation cost of this account. + /// - **`seeds = [Config::SEED_PREFIX]`**: Sets the PDA (program-derived address) seed that + /// uniquely identifies the `config` account. This ensures that the correct PDA is referenced. + /// - **`bump`**: Used in combination with the seeds to find the PDA. The `bump` ensures a valid PDA + /// that is not already taken by another account. + /// - **`space = Config::MAXIMUM_SIZE`**: Allocates the appropriate amount of space for the `config` account's data. + /// + /// ## Attributes + /// + /// - **`init`**: Indicates that this account should be initialized by the instruction. + /// - **`payer = owner`**: Specifies that the `owner` account will pay for the account's rent and creation. + /// - **`seeds = [Config::SEED_PREFIX]`**: Defines the seed used to derive the PDA for the `config` account. + /// - **`bump`**: Provides the bump seed necessary for PDA derivation. + /// - **`space = Config::MAXIMUM_SIZE`**: Allocates sufficient space for the `config` account's data. #[account( init, payer = owner, @@ -32,13 +43,17 @@ pub struct Initialize<'info> { space = Config::MAXIMUM_SIZE, )] /// The `config` account that stores program data needed for other instructions. + /// /// It is created on initialization, ensuring that all subsequent operations /// have a consistent place to store relevant configuration information. pub config: Account<'info, Config>, - // The `system_program` is the program that is responsible for creating and - // allocating accounts. It is necessary whenever new accounts need to be - // created and funded. - /// The standard system program, required here to create and fund the `config` account. + /// The `system_program` is the program responsible for creating and allocating accounts. + /// + /// It is necessary whenever new accounts need to be created and funded. + /// + /// ## Attributes + /// + /// - **Standard System Program**: Required here to create and fund the `config` account. pub system_program: Program<'info, System>, } diff --git a/packages/solana/programs/snapshotter/src/contexts/subscribe.rs b/packages/solana/programs/snapshotter/src/contexts/subscribe.rs index 50efbcdb..aee7fbce 100644 --- a/packages/solana/programs/snapshotter/src/contexts/subscribe.rs +++ b/packages/solana/programs/snapshotter/src/contexts/subscribe.rs @@ -2,20 +2,36 @@ use crate::*; #[derive(Accounts)] pub struct Subscribe<'info> { - // The `config` account represents a piece of the program's state, previously initialized and stored on-chain. - // By including `seeds = [Config::SEED_PREFIX]` and `bump`, this indicates that the `config` account's - // public key is derived using a Program-Derived Address (PDA) approach. The `bump` is an auto-calculated - // value that ensures the generated PDA does not collide with an existing account. - // - // The `mut` keyword means that this account will be modified during the execution of the instruction. - // Common modifications may include incrementing counters, logging subscription events, or updating other - // relevant fields that track user subscriptions. + /// The `config` account represents a piece of the program's state, previously initialized and stored on-chain. + /// By including `seeds = [Config::SEED_PREFIX]` and `bump`, this indicates that the `config` account's + /// public key is derived using a Program-Derived Address (PDA) approach. The `bump` is an auto-calculated + /// value that ensures the generated PDA does not collide with an existing account. + /// + /// The `mut` keyword means that this account will be modified during the execution of the instruction. + /// Common modifications may include incrementing counters, logging subscription events, or updating other + /// relevant fields that track user subscriptions. #[account( seeds = [Config::SEED_PREFIX], bump, mut )] - /// The `config` account that holds data relevant to the subscription logic. This - /// account is expected to be pre-initialized and possibly managed by earlier steps in the program. + /// The `config` account that holds data relevant to the subscription logic. + /// + /// This account is expected to be pre-initialized and possibly managed by earlier steps in the program. + /// + /// ## Attributes + /// + /// - **`seeds = [Config::SEED_PREFIX]`**: + /// - **Purpose**: Defines the seed used to derive the PDA for the `config` account. + /// - **Function**: Ensures that the account address is uniquely and deterministically derived based on the provided seed. + /// - **Security**: Prevents unauthorized accounts from masquerading as the `config` account by enforcing a specific derivation path. + /// + /// - **`bump`**: + /// - **Purpose**: A nonce used alongside the seeds to find a valid PDA that does not collide with existing accounts. + /// - **Function**: Anchor automatically calculates and provides the bump value required for PDA derivation. + /// + /// - **`mut`**: + /// - **Purpose**: Marks the `config` account as mutable, allowing its data to be modified during instruction execution. + /// - **Function**: Enables the program to update fields within the `Config` account, such as adding a new subscription. pub config: Account<'info, Config>, } diff --git a/packages/solana/programs/snapshotter/src/lib.rs b/packages/solana/programs/snapshotter/src/lib.rs index e16b5b6f..8035d439 100644 --- a/packages/solana/programs/snapshotter/src/lib.rs +++ b/packages/solana/programs/snapshotter/src/lib.rs @@ -34,29 +34,59 @@ pub mod snapshotter { // Determines how many accounts are processed per batch during root calculation. pub const BATCH_SIZE: usize = 10; - // Initializes the `Config` account when the program is first set up. - // Sets the root to a default value, marks it as not finalized, and - // sets the expected batch to zero, preparing the system for future operations. + /// Initializes the `Config` account when the program is first set up. + /// + /// This function sets the initial state of the `Config` account by: + /// - Setting the `root` to a default hash value. + /// - Marking the `root_finalized` flag as `false`. + /// - Setting the `expected_batch` to `0`. + /// - Initializing the `nonce` to `0`. + /// + /// These initializations prepare the system for future operations related to snapshotting. + /// + /// # Arguments + /// + /// * `ctx` - The context containing all the accounts required for initialization. + /// + /// # Returns + /// + /// * `Result<()>` - Returns `Ok(())` if successful, or an error otherwise. pub fn initialize(ctx: Context) -> Result<()> { let config = &mut ctx.accounts.config; + // Set the root to a default hash value (all zeros) config.root = Hash::default().to_bytes(); + // Mark the root as not finalized config.root_finalized = false; + // Set the expected batch to zero, indicating that the first batch to process is batch 0 config.expected_batch = 0; + // Initialize the nonce to zero, which can be used for versioning or replay protection config.nonce = 0; Ok(()) } - // Subscribes a new account to the `subscribed_accounts` list within the `Config`. - // This function ensures that the account is not already subscribed before adding it. + /// Subscribes a new account to the `subscribed_accounts` list within the `Config`. + /// + /// This function ensures that the account is not already subscribed before adding it to prevent duplicates. + /// + /// # Arguments + /// + /// * `ctx` - The context containing all the accounts required for subscription. + /// * `account_to_subscribe` - The public key of the account to be subscribed. + /// + /// # Returns + /// + /// * `Result<()>` - Returns `Ok(())` if successful, or an error otherwise. pub fn subscribe(ctx: Context, account_to_subscribe: Pubkey) -> Result<()> { let config = &mut ctx.accounts.config; + // Check if the account is already subscribed to prevent duplicates if config.subscribed_accounts.contains(&account_to_subscribe) { return Err(error!(ErrorCode::AccountAlreadySubscribed)); } + // Add the new account to the list of subscribed accounts config.subscribed_accounts.push(account_to_subscribe); Ok(()) @@ -79,37 +109,48 @@ pub mod snapshotter { pub fn calculate_root(ctx: Context, batch: u64) -> Result<()> { let config = &mut ctx.accounts.config; + // Step 1: Verify that the provided batch number matches the expected batch if batch != config.expected_batch { return Err(error!(ErrorCode::InvalidBatch)); } + // Determine if the current batch is the last batch let is_last_batch = ((config.subscribed_accounts.len() / BATCH_SIZE) as u64) == batch; + // Step 2: Verify the number of remaining accounts if (is_last_batch && ctx.remaining_accounts.len() > BATCH_SIZE) || (!is_last_batch && ctx.remaining_accounts.len() != BATCH_SIZE) { return Err(error!(ErrorCode::InvalidRemainingAccountsLength)); } + // Step 3: Finalize or prepare for the next batch if is_last_batch { + // If it's the last batch, finalize the root and reset for future operations config.root_finalized = true; config.expected_batch = 0; config.nonce += 1; } else { + // If not the last batch, prepare for the next batch config.root_finalized = false; config.expected_batch += 1; } let mut account_hashes = Vec::new(); + // Calculate the starting index for the current batch let start_index: usize = (batch * BATCH_SIZE as u64).try_into().unwrap(); + // Step 4: Iterate over the accounts in the current batch for (index, account) in ctx.remaining_accounts.iter().enumerate() { + // Verify that the account is indeed subscribed and in the correct order if *account.key != config.subscribed_accounts[start_index + index] { return Err(error!(ErrorCode::InvalidSubscribedAccount)); } + // Borrow the lamports (SOL balance) and data of the account for hashing let lamport_ref = account.lamports.borrow(); let data_ref = account.data.borrow(); + // Compute the hash of the account's state account_hashes.push(account_hasher( &account.key, **lamport_ref, @@ -119,8 +160,10 @@ pub mod snapshotter { )); } + // Step 5: Update the Merkle Mountain Range (MMR) with the new account hashes let mut mmr = MerkleMountainRange::from(Hash::new_from_array(config.root)); mmr.update_root(account_hashes)?; + // Store the updated root back into the `Config` config.root = mmr.root.to_bytes(); Ok(()) diff --git a/packages/solana/programs/snapshotter/src/state/config.rs b/packages/solana/programs/snapshotter/src/state/config.rs index 732f2bfb..def261a3 100644 --- a/packages/solana/programs/snapshotter/src/state/config.rs +++ b/packages/solana/programs/snapshotter/src/state/config.rs @@ -3,55 +3,68 @@ use crate::*; #[account] #[derive(Default)] pub struct Config { - // A list of Pubkeys (addresses) that are considered to be subscribed - // to something within the context of this program (e.g., updates, notifications, etc.). + /// A list of `Pubkey`s (public keys) representing accounts that are subscribed to updates, notifications, or other relevant events + /// within the context of this program. + /// + /// - **Purpose**: To keep track of all accounts that need to be monitored or included in snapshot calculations. + /// - **Usage**: Other instructions can reference this list to perform actions like notifying subscribers or including their data in computations. pub subscribed_accounts: Vec, - // A 32-byte value representing some form of root data. This could be, for example, a Merkle root - // used to verify the integrity of a dataset or something similar that needs to be referenced - // persistently across multiple instructions. + /// A 32-byte array representing a cryptographic root, such as a Merkle root. + /// + /// - **Purpose**: To verify the integrity of a dataset or to provide a reference point for subsequent operations. + /// - **Usage**: This root is used across multiple instructions to ensure consistency and validity of the data being processed. pub root: [u8; 32], - // A boolean flag indicating whether the `root` is finalized. If `true`, it might mean - // no further changes to the `root` are allowed, or that some condition has been met. + /// A boolean flag indicating whether the current `root` has been finalized. + /// + /// - **Purpose**: To determine if the `root` is in a stable state and no further modifications are expected. + /// - **Usage**: Finalized roots might trigger specific actions or prevent further changes to ensure data integrity. pub root_finalized: bool, - // An unsigned 64-bit integer that might represent an expected batch number or - // counter for a process that runs periodically or sequentially. + /// An unsigned 64-bit integer representing the expected batch number for root calculations. + /// + /// - **Purpose**: To manage and track the progression of batch processing, ensuring that roots are calculated in the correct sequence. + /// - **Usage**: Helps in synchronizing batch operations and preventing out-of-order processing. pub expected_batch: u64, - // An unsigned 64-bit integer that represent the number of calculated roots + /// An unsigned 64-bit integer serving as a nonce, representing the number of calculated roots. + /// + /// - **Purpose**: To provide a unique identifier for each root calculation cycle, aiding in versioning and replay protection. + /// - **Usage**: Incremented each time a new root is calculated, ensuring that each root is distinct and traceable. pub nonce: u64, } -// `impl Config` block provides associated functions for `Config`. impl Config { - // MAXIMUM_SIZE provides a static size allocation for this account’s storage. - // Anchor requires specifying account size, and this constant ensures that the - // account is allocated enough space for the data it holds. - // - // Explanation of each term: - // - 8 bytes for the account discriminator (Anchor uses an 8-byte prefix to identify account types) - // - 4 bytes for the `subscribed_accounts` vector's length (since the vector is variable-length, - // its length is stored as a 32-bit integer) - // - (32 * 256) bytes for the maximum number of `Pubkey`s we anticipate storing. Each `Pubkey` is 32 bytes, - // and we’re currently limiting ourselves to 256 of them. - // - 32 bytes for the `root` array - // - 1 byte for the boolean `root_finalized` - // - 8 bytes for the `expected_batch` (u64) - // - // In the future, if we need to store more than 256 `Pubkey`s, we might consider - // reallocation (using `realloc` in Anchor) or a PDA-based approach to store additional data. + /// `MAXIMUM_SIZE` defines the total byte size allocated for the `Config` account. + /// + /// Anchor requires specifying the exact account size to allocate storage on the blockchain. + /// This constant ensures that the account is allocated enough space for all its fields. + /// + /// **Breakdown of `MAXIMUM_SIZE`:** + /// - `8` bytes: Account discriminator (used by Anchor to identify account types). + /// - `4` bytes: Length prefix for the `subscribed_accounts` vector (`Vec`). + /// - `32 * 256` bytes: Maximum storage for `subscribed_accounts`. Each `Pubkey` is `32` bytes, and the vector is limited to `256` entries. + /// - `32` bytes: The `root` array. + /// - `1` byte: The `root_finalized` boolean flag. + /// - `8` bytes: The `expected_batch` (`u64`). + /// - `8` bytes: The `nonce` (`u64`). + /// + /// **Total**: `8 + 4 + (32 * 256) + 32 + 1 + 8 + 8 = 8 + 4 + 8192 + 32 + 1 + 8 + 8 = 82653` bytes. + /// + /// **Note**: The maximum number of `Pubkey`s (`256`) can be adjusted based on program requirements. If more are needed, + /// consider using dynamic allocation techniques or multiple accounts to store additional data. pub const MAXIMUM_SIZE: usize = 8 // discriminator + 4 // subscribed_accounts vec length + (32 * 256) // max subscribed_accounts data + 32 // root + 1 // root_finalized - + 8 // expected_batch - + 8; // nonce + + 8 // expected_batch (u64) + + 8; // nonce (u64) - // The seed prefix is a static byte array used as part of the seeds to derive - // the program's `Config` account's PDA (Program-Derived Address). - // Using a well-known, stable prefix ensures that we can reliably find the `Config` PDA. + /// `SEED_PREFIX` is a static byte array used as a seed for deriving the Program Derived Address (PDA) of the `Config` account. + /// + /// - **Purpose**: To ensure that the PDA is uniquely and deterministically derived, preventing address collisions. + /// - **Usage**: Combined with other seeds and a bump value to generate a secure PDA that the program can control. pub const SEED_PREFIX: &'static [u8; 6] = b"config"; } From a1b35a0d7d37626bb8ffcf9ae97e6433ca06beb2 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 18 Dec 2024 07:54:49 +0100 Subject: [PATCH 23/31] feat(solana): rm dispatch_slot in favour of dispatch_root within debridge_reporter and rm slots --- packages/solana/Cargo.lock | 9 +- .../programs/debridge-reporter/Cargo.toml | 4 +- .../src/contexts/dispatch_root.rs | 51 ++++++++++++ .../src/contexts/dispatch_slot.rs | 9 -- .../src/contexts/initialize.rs | 72 ++++++++++++++++ .../debridge-reporter/src/contexts/mod.rs | 6 +- .../programs/debridge-reporter/src/error.rs | 12 +++ .../programs/debridge-reporter/src/lib.rs | 83 +++++++++++++++++-- .../debridge-reporter/src/state/config.rs | 42 ++++++++++ .../debridge-reporter/src/state/mod.rs | 3 + .../solana/programs/snapshotter/src/error.rs | 1 - .../src/contexts/initialize.rs | 1 - .../programs/wormhole-reporter/src/error.rs | 9 +- packages/solana/shared/slots/Cargo.toml | 16 ---- packages/solana/shared/slots/src/lib.rs | 46 ---------- 15 files changed, 266 insertions(+), 98 deletions(-) create mode 100644 packages/solana/programs/debridge-reporter/src/contexts/dispatch_root.rs delete mode 100644 packages/solana/programs/debridge-reporter/src/contexts/dispatch_slot.rs create mode 100644 packages/solana/programs/debridge-reporter/src/contexts/initialize.rs create mode 100644 packages/solana/programs/debridge-reporter/src/error.rs create mode 100644 packages/solana/programs/debridge-reporter/src/state/config.rs create mode 100644 packages/solana/programs/debridge-reporter/src/state/mod.rs delete mode 100644 packages/solana/shared/slots/Cargo.toml delete mode 100644 packages/solana/shared/slots/src/lib.rs diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index 10f6c66d..dba4c42d 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -1177,7 +1177,7 @@ dependencies = [ "anchor-lang", "debridge-solana-sdk", "message", - "slots", + "snapshotter", ] [[package]] @@ -2700,13 +2700,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "slots" -version = "0.1.0" -dependencies = [ - "anchor-lang", -] - [[package]] name = "smallvec" version = "1.13.2" diff --git a/packages/solana/programs/debridge-reporter/Cargo.toml b/packages/solana/programs/debridge-reporter/Cargo.toml index 8af05c85..46db19f8 100644 --- a/packages/solana/programs/debridge-reporter/Cargo.toml +++ b/packages/solana/programs/debridge-reporter/Cargo.toml @@ -19,5 +19,5 @@ idl-build = ["anchor-lang/idl-build"] [dependencies] anchor-lang = "0.30.1" debridge-solana-sdk = { git = "ssh://git@github.com/debridge-finance/debridge-solana-sdk.git", version = "1.0.2" } -slots = { path = "../../shared/slots" } -message = { path = "../../shared/message" } \ No newline at end of file +message = { path = "../../shared/message" } +snapshotter = { path = "../snapshotter", default-features = false, features = ["cpi"] } \ No newline at end of file diff --git a/packages/solana/programs/debridge-reporter/src/contexts/dispatch_root.rs b/packages/solana/programs/debridge-reporter/src/contexts/dispatch_root.rs new file mode 100644 index 00000000..3e65f450 --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/contexts/dispatch_root.rs @@ -0,0 +1,51 @@ +use anchor_lang::prelude::*; + +use crate::{error::ErrorCode, state::Config}; + +#[derive(Accounts)] +pub struct DispatchRoot<'info> { + /// The `config` account holds the snapshotter's configuration and state. + /// + /// - **PDA Derivation**: The account is a PDA derived using the `Config::SEED_PREFIX` as the seed. This ensures + /// that the account address is uniquely identified and securely accessed by the program. + /// + /// - **Bump Seed**: The `bump` attribute is used to derive the PDA alongside the seeds. It guarantees that the PDA + /// is valid and helps prevent collisions with other accounts. + /// + /// - **Read-Only**: The absence of the `mut` keyword indicates that this account will not be modified during + /// the instruction execution. + #[account( + seeds = [Config::SEED_PREFIX], + bump, + )] + /// Config account. + pub config: Account<'info, Config>, + + /// The `snapshotter_config` account represents the snapshotter's configuration. + /// + /// - **Mutability**: Marked as `mut` to allow modifications during the instruction execution. + /// - **Address Constraint**: Ensures that the provided `snapshotter_config` account matches the + /// `snapshotter_config` specified within the `config` account. If there is a mismatch, + /// the program will throw the `InvalidSnapshotterConfig` error. + /// + /// - **CHECK Annotation**: + /// - **Purpose**: Indicates to Anchor that this account requires manual validation. + /// - **Reason**: Since `UncheckedAccount` bypasses Anchor's type and ownership checks, the developer + /// must ensure that the account is valid and correctly matches the expected configuration. + /// + /// ## Security Considerations: + /// - **Manual Validation**: Developers must ensure that the `snapshotter_config` account is trustworthy + /// and correctly corresponds to the one stored in `config`. Failing to do so can lead to unauthorized + /// modifications or inconsistencies in the program's state. + /// + /// ## Error Handling: + /// - **`ErrorCode::InvalidSnapshotterConfig`**: + /// - **Trigger**: Thrown when the `snapshotter_config` account's public key does not match the one specified in `config`. + /// - **Purpose**: Prevents unauthorized or incorrect accounts from being used, ensuring the integrity of the snapshotter's configuration. + #[account( + mut, + address = config.snapshotter_config @ ErrorCode::InvalidSnapshotterConfig + )] + /// CHECK: Snapshotter program + pub snapshotter_config: UncheckedAccount<'info>, +} diff --git a/packages/solana/programs/debridge-reporter/src/contexts/dispatch_slot.rs b/packages/solana/programs/debridge-reporter/src/contexts/dispatch_slot.rs deleted file mode 100644 index 0fbefcab..00000000 --- a/packages/solana/programs/debridge-reporter/src/contexts/dispatch_slot.rs +++ /dev/null @@ -1,9 +0,0 @@ -use anchor_lang::prelude::*; -use anchor_lang::solana_program::sysvar; - -#[derive(Accounts)] -pub struct DispatchSlot<'info> { - /// CHECK: We are reading from SlotHashes sysvar the latest slot hash - #[account(address = sysvar::slot_hashes::ID)] - pub slot_hashes: AccountInfo<'info>, -} diff --git a/packages/solana/programs/debridge-reporter/src/contexts/initialize.rs b/packages/solana/programs/debridge-reporter/src/contexts/initialize.rs new file mode 100644 index 00000000..477e8b97 --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/contexts/initialize.rs @@ -0,0 +1,72 @@ +use anchor_lang::prelude::*; + +use crate::state::Config; + +#[derive(Accounts)] +pub struct Initialize<'info> { + /// The `owner` is a Signer account, indicating that whoever calls this instruction + /// must sign the transaction with their private key. This ensures that the initializer + /// has authority. + /// + /// `#[account(mut)]` is used here because the `owner` account's lamports are used + /// to fund the creation of the `config` account. + /// + /// ## Attributes + /// + /// - **`mut`**: Marks the `owner` account as mutable, allowing its lamports to be debited. + #[account(mut)] + /// Whoever initializes the config will be the owner of the program. Signer + /// for creating the [`Config`] account. + pub owner: Signer<'info>, + + /// The `config` account will be created (initialized) by this instruction. + /// + /// The `init` attribute indicates that this account should be created (allocated and assigned) + /// and initialized with the given seeds, bump, and space. + /// + /// - **`payer = owner`**: The `owner` account pays for the rent and creation cost of this account. + /// - **`seeds = [Config::SEED_PREFIX]`**: Sets the PDA (program-derived address) seed that + /// uniquely identifies the `config` account. This ensures that the correct PDA is referenced. + /// - **`bump`**: Used in combination with the seeds to find the PDA. The `bump` ensures a valid PDA + /// that is not already taken by another account. + /// - **`space = Config::MAXIMUM_SIZE`**: Allocates the appropriate amount of space for the `config` account's data based on the `Config` structure. + /// + /// ## Attributes + /// + /// - **`init`**: Indicates that this account should be initialized by the instruction. + /// - **`payer = owner`**: Specifies that the `owner` account will pay for the account's rent and creation. + /// - **`seeds = [Config::SEED_PREFIX]`**: Defines the seed used to derive the PDA for the `config` account. + /// - **`bump`**: Provides the bump seed necessary for PDA derivation. + /// - **`space = Config::MAXIMUM_SIZE`**: Allocates sufficient space for the `config` account's data. + #[account( + init, + payer = owner, + seeds = [Config::SEED_PREFIX], + bump, + space = Config::MAXIMUM_SIZE, + )] + /// Config account, which saves program data useful for other instructions. + /// + /// It is created on initialization, ensuring that all subsequent operations + /// have a consistent place to store relevant configuration information. + pub config: Account<'info, Config>, + + /// The `snapshotter_config` account represents the snapshotter's configuration. + /// + /// - **UncheckedAccount**: The `snapshotter_config` is marked as `UncheckedAccount`, meaning that Anchor will + /// not perform any type or ownership checks on this account. It is the developer's responsibility to ensure + /// that this account is valid and correctly matches the expected configuration. + /// + /// - **Purpose**: Represents the snapshotter's configuration. Although marked as `UncheckedAccount`, it should be correctly associated with the `Config` account to maintain program integrity. + /// CHECK: Snapshotter program + pub snapshotter_config: UncheckedAccount<'info>, + + /// The `system_program` is the program responsible for creating and allocating accounts. + /// + /// It is necessary whenever new accounts need to be created and funded. + /// + /// ## Attributes + /// + /// - **Standard System Program**: Required here to create and fund the `config` account. + pub system_program: Program<'info, System>, +} diff --git a/packages/solana/programs/debridge-reporter/src/contexts/mod.rs b/packages/solana/programs/debridge-reporter/src/contexts/mod.rs index ce3e13db..c8092b30 100644 --- a/packages/solana/programs/debridge-reporter/src/contexts/mod.rs +++ b/packages/solana/programs/debridge-reporter/src/contexts/mod.rs @@ -1,3 +1,5 @@ -pub mod dispatch_slot; +pub mod dispatch_root; +pub mod initialize; -pub use dispatch_slot::*; +pub use dispatch_root::*; +pub use initialize::*; diff --git a/packages/solana/programs/debridge-reporter/src/error.rs b/packages/solana/programs/debridge-reporter/src/error.rs new file mode 100644 index 00000000..dd6c313d --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/error.rs @@ -0,0 +1,12 @@ +use anchor_lang::prelude::error_code; + +#[error_code] +pub enum ErrorCode { + #[msg("InvalidSnapshotterConfig")] + /// Invalid Snapshotter config + InvalidSnapshotterConfig, + + #[msg("RootNotFinalized")] + /// Snapshotter root not finalized + RootNotFinalized, +} diff --git a/packages/solana/programs/debridge-reporter/src/lib.rs b/packages/solana/programs/debridge-reporter/src/lib.rs index 2891ed62..de640fd3 100644 --- a/packages/solana/programs/debridge-reporter/src/lib.rs +++ b/packages/solana/programs/debridge-reporter/src/lib.rs @@ -1,28 +1,94 @@ use anchor_lang::prelude::*; -declare_id!("7GPwvvhq33fTYuDyfA1JVz4fp3XkdcmjerJWpUkxjrC2"); +declare_id!("DkJFdedMeprFUzymuZpvXCTqcUt1zc8uz45UgajsKbWH"); pub mod contexts; +pub mod error; +pub mod state; pub use contexts::*; +pub use error::ErrorCode; +pub use state::*; #[program] pub mod debridge_reporter { use super::*; use debridge_solana_sdk::sending; use message::Message; - use slots::get_slot; + use snapshotter::state::Config as SnapshotterConfig; - pub fn dispatch_slot( - ctx: Context, + /// Initializes the `snapshotter_config` within the `Config` account. + /// + /// This function sets the `snapshotter_config` field in the `Config` account to point to the `Config` account's own public key. + /// This establishes a direct reference, ensuring that the `snapshotter_config` is correctly linked. + /// + /// ## Arguments + /// + /// - `ctx`: The context containing the `Initialize` accounts. + /// + /// ## Returns + /// + /// - `Result<()>`: Returns `Ok(())` if successful, or an error otherwise. + pub fn initialize(ctx: Context) -> Result<()> { + let config = &mut ctx.accounts.config; + + // Set the `snapshotter_config` field in the `Config` account to the public key of the `Config` account itself. + // This creates a self-reference, establishing a direct link to the snapshotter's configuration. + config.snapshotter_config = ctx.accounts.snapshotter_config.key(); + Ok(()) + } + + /// Dispatches a slot by sending a message via DeBridge to a target chain. + /// + /// This function performs the following steps: + /// 1. Deserializes the `snapshotter_config` data to access the current configuration. + /// 2. Checks if the current `root` is finalized. If not, it returns an error. + /// 3. Creates a DeBridge `Message` containing the `nonce` and `root`. + /// 4. Serializes the `Message` into a byte payload. + /// 5. Invokes the DeBridge `send_message` function to dispatch the message to the target chain. + /// + /// ## Arguments + /// + /// - `ctx`: The context containing the `DispatchRoot` accounts. + /// - `target_chain_id`: A 32-byte identifier representing the target blockchain where the message should be sent. + /// - `receiver`: A vector of bytes representing the receiver's address on the target chain. + /// + /// ## Returns + /// + /// - `Result<()>`: Returns `Ok(())` if the message is successfully dispatched, or an error otherwise. + pub fn dispatch_root( + ctx: Context, target_chain_id: [u8; 32], receiver: Vec, - slot_number: u64, ) -> Result<()> { - let slot_hash = get_slot(&ctx.accounts.slot_hashes, slot_number)?; - let message = Message::from((slot_number, slot_hash)); + // Deserialize the snapshotter configuration data from the `snapshotter_config` account. + // This allows access to fields like `nonce` and `root`. + let mut data_slice: &[u8] = &ctx.accounts.snapshotter_config.data.borrow(); + let snapshotter_config: SnapshotterConfig = + AccountDeserialize::try_deserialize(&mut data_slice)?; + + // Ensure that the `root` has been finalized before proceeding. + // If the root is not finalized, return an error to prevent dispatching incomplete or unstable data. + if !snapshotter_config.root_finalized { + return Err(error!(ErrorCode::RootNotFinalized)); + } + + // Create a DeBridge `Message` from the snapshotter's `nonce` and `root`. + // This message serves as a data payload to be sent to the target chain. + let message = Message::from((snapshotter_config.nonce, snapshotter_config.root)); + + // Serialize the `Message` into a byte vector (`payload`) for transmission. let mut payload: Vec = Vec::new(); message.serialize(&mut payload)?; + + // Invoke the DeBridge `send_message` function to dispatch the serialized message. + // Parameters: + // - `payload`: The serialized message to be sent. + // - `target_chain_id`: The identifier of the target blockchain. + // - `receiver`: The address on the target chain that should receive the message. + // - `0`: Execution fee. A value of `0` typically means that the fee is automatically handled or claimed. + // - `vec![0u8; 32]`: Fallback address. This can be used in case the message fails to be processed on the target chain. + // - `ctx.remaining_accounts`: Any additional accounts required for the DeBridge CPI (Cross-Program Invocation). sending::invoke_send_message( payload, target_chain_id, @@ -31,7 +97,8 @@ pub mod debridge_reporter { vec![0u8; 32], // fallback address ctx.remaining_accounts, ) - .map_err(ProgramError::from)?; + .map_err(ProgramError::from)?; // Convert any errors from the CPI into Anchor's error type. + Ok(()) } } diff --git a/packages/solana/programs/debridge-reporter/src/state/config.rs b/packages/solana/programs/debridge-reporter/src/state/config.rs new file mode 100644 index 00000000..a5a753c7 --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/state/config.rs @@ -0,0 +1,42 @@ +use anchor_lang::prelude::*; + +#[account] +#[derive(Default)] +pub struct Config { + /// Snapshotter config address. + /// + /// - **Type**: `Pubkey` + /// - **Purpose**: + /// - Stores the public key of the `snapshotter_config` account. + /// - This address is used to reference and interact with the snapshotter's configuration. + /// - Ensures that the program can locate and validate the snapshotter's configuration during operations. + pub snapshotter_config: Pubkey, +} + +impl Config { + /// `MAXIMUM_SIZE` defines the total byte size allocated for the `Config` account. + /// + /// Anchor requires specifying the exact account size to allocate storage on the blockchain. + /// This constant ensures that the account is allocated enough space for all its fields. + /// + /// **Breakdown of `MAXIMUM_SIZE`:** + /// - `8` bytes: Account discriminator (used by Anchor to identify account types). + /// - `32` bytes: The `snapshotter_config` field, which is a `Pubkey` (32 bytes). + /// + /// **Total `MAXIMUM_SIZE`**: `8 + 32 = 40` bytes. + /// + /// **Note**: Currently, the `Config` struct contains only one field. If additional fields are added in the future, + /// update the `MAXIMUM_SIZE` accordingly to accommodate the new data. + pub const MAXIMUM_SIZE: usize = 8 // discriminator + + 32; // snapshotter_config + + /// `SEED_PREFIX` is a static byte array used as a seed for deriving the Program Derived Address (PDA) of the `Config` account. + /// + /// - **Type**: `&'static [u8; 6]` + /// - **Value**: `b"config"` + /// - **Purpose**: + /// - Provides a unique and consistent seed used in PDA derivation. + /// - Ensures that the PDA for the `Config` account is deterministic and can be reliably regenerated. + /// - Helps prevent address collisions by using a well-known, stable prefix. + pub const SEED_PREFIX: &'static [u8; 6] = b"config"; +} diff --git a/packages/solana/programs/debridge-reporter/src/state/mod.rs b/packages/solana/programs/debridge-reporter/src/state/mod.rs new file mode 100644 index 00000000..a9217b9c --- /dev/null +++ b/packages/solana/programs/debridge-reporter/src/state/mod.rs @@ -0,0 +1,3 @@ +pub mod config; + +pub use config::*; diff --git a/packages/solana/programs/snapshotter/src/error.rs b/packages/solana/programs/snapshotter/src/error.rs index 625e737b..9f0ab4aa 100644 --- a/packages/solana/programs/snapshotter/src/error.rs +++ b/packages/solana/programs/snapshotter/src/error.rs @@ -1,7 +1,6 @@ use anchor_lang::prelude::*; #[error_code] -/// Errors relevant to this program's malfunction. pub enum ErrorCode { #[msg("AccountAlreadySubscribed")] /// An account is already subscribed diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs index 2a6b3763..dbcec6b3 100644 --- a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs +++ b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs @@ -7,7 +7,6 @@ use crate::state::{Config, WormholeEmitter}; pub const SEED_PREFIX_SENT: &[u8; 4] = b"sent"; #[derive(Accounts)] -/// Context used to initialize program data (i.e. config). pub struct Initialize<'info> { #[account(mut)] /// Whoever initializes the config will be the owner of the program. Signer diff --git a/packages/solana/programs/wormhole-reporter/src/error.rs b/packages/solana/programs/wormhole-reporter/src/error.rs index 2bb3398c..b977c67b 100644 --- a/packages/solana/programs/wormhole-reporter/src/error.rs +++ b/packages/solana/programs/wormhole-reporter/src/error.rs @@ -1,7 +1,6 @@ use anchor_lang::prelude::error_code; #[error_code] -/// Errors relevant to this program's malfunction. pub enum ErrorCode { #[msg("InvalidWormholeConfig")] /// Specified Wormhole bridge data PDA is wrong. @@ -19,11 +18,11 @@ pub enum ErrorCode { /// Specified sysvar is wrong. InvalidSysvar, - #[msg("RootNotFinalized")] - /// Snapshotter root not finalized - RootNotFinalized, - #[msg("InvalidSnapshotterConfig")] /// Invalid Snapshotter config InvalidSnapshotterConfig, + + #[msg("RootNotFinalized")] + /// Snapshotter root not finalized + RootNotFinalized, } diff --git a/packages/solana/shared/slots/Cargo.toml b/packages/solana/shared/slots/Cargo.toml deleted file mode 100644 index a62818ab..00000000 --- a/packages/solana/shared/slots/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "slots" -version = "0.1.0" -description = "Utilities functions to access Solana slots" -edition = "2021" - -[features] -default = [] -cpi = ["no-entrypoint"] -no-entrypoint = [] -no-idl = [] -no-log-ix-name = [] -idl-build = ["anchor-lang/idl-build"] - -[dependencies] -anchor-lang = "0.30.1" \ No newline at end of file diff --git a/packages/solana/shared/slots/src/lib.rs b/packages/solana/shared/slots/src/lib.rs deleted file mode 100644 index 53f0aa51..00000000 --- a/packages/solana/shared/slots/src/lib.rs +++ /dev/null @@ -1,46 +0,0 @@ -use anchor_lang::prelude::*; -use anchor_lang::solana_program::sysvar; - -pub fn get_slot(slot_hashes: &AccountInfo, slot_number: u64) -> Result<[u8; 32]> { - if *slot_hashes.key != sysvar::slot_hashes::ID { - return Err(error!(ErrorCode::InvalidSlotHashesSysVar)); - } - - let data = slot_hashes.try_borrow_data()?; - let num_slot_hashes = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let mut pos = 8; - - if num_slot_hashes == 0 { - return Err(error!(ErrorCode::SlotHashesNotAvailable)); - } - - for _i in 0..num_slot_hashes { - let current_slot_number = u64::from_le_bytes(data[pos..pos + 8].try_into().unwrap()); - pos += 8; - - let current_slot_hash: [u8; 32] = match &data[pos..pos + 32].try_into() { - Ok(hash) => *hash, - Err(_) => return Err(error!(ErrorCode::InvalidLatestHashLength)), - }; - - if current_slot_number == slot_number { - return Ok(current_slot_hash); - } - - pos += 32; - } - - Err(error!(ErrorCode::SlotNotFound)) -} - -#[error_code] -pub enum ErrorCode { - #[msg("Invalid latest hash hash.")] - InvalidLatestHashLength, - #[msg("Invalid slot hashes sysvar.")] - InvalidSlotHashesSysVar, - #[msg("Slot hashes not available.")] - SlotHashesNotAvailable, - #[msg("Slot not found")] - SlotNotFound, -} From de794ad120402d429b6689f252e7e116506c7e4e Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 18 Dec 2024 08:10:30 +0100 Subject: [PATCH 24/31] refactor(solana): adds missing comments to wormhole_reporter --- .../src/contexts/dispatch_root.rs | 144 +++++++++++++++- .../src/contexts/initialize.rs | 163 +++++++++++++++++- .../wormhole-reporter/src/state/config.rs | 72 ++++++-- .../src/state/wormhole_emitter.rs | 18 +- 4 files changed, 366 insertions(+), 31 deletions(-) diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_root.rs b/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_root.rs index 4422c76a..46b2d143 100644 --- a/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_root.rs +++ b/packages/solana/programs/wormhole-reporter/src/contexts/dispatch_root.rs @@ -11,10 +11,36 @@ const SEED_PREFIX_SENT: &[u8; 4] = b"sent"; #[derive(Accounts)] pub struct DispatchRoot<'info> { + /// The `payer` is responsible for paying the Wormhole fee to post a message. + /// + /// - **Type**: `Signer<'info>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the `payer` account may be mutated (e.g., lamports debited) during the instruction. + /// + /// ## Purpose: + /// Ensures that the entity dispatching the root has the authority and funds to cover the necessary fees. + /// + /// ## Security Considerations: + /// - **Authority**: Only authorized signers should be able to invoke this instruction to prevent unauthorized fee payments. + /// - **Funds Management**: Ensures that the payer has sufficient lamports to cover the Wormhole fee. #[account(mut)] /// Payer will pay Wormhole fee to post a message. pub payer: Signer<'info>, + /// The `config` account holds the snapshotter's configuration and state. + /// + /// - **Type**: `Account<'info, Config>` + /// - **Attributes**: + /// - **`seeds = [Config::SEED_PREFIX]`**: Specifies that the `config` account is derived from a PDA using `Config::SEED_PREFIX` as the seed. + /// - **`bump`**: The bump seed used in conjunction with the seeds to find the PDA. + /// + /// ## Purpose: + /// Acts as the central configuration hub, storing essential data required for dispatching roots, + /// managing subscriptions, and maintaining program integrity. + /// + /// ## Security Considerations: + /// - **PDA Derivation**: Ensures that the correct `config` account is accessed, preventing unauthorized access. + /// - **Read-Only**: Not marked as mutable, indicating that it won't be modified during this instruction, enhancing security by preventing unintended state changes. #[account( seeds = [Config::SEED_PREFIX], bump, @@ -23,9 +49,29 @@ pub struct DispatchRoot<'info> { /// against the Wormhole accounts in this context. Read-only. pub config: Account<'info, Config>, - /// Wormhole program. + /// The `wormhole_program` is the Wormhole protocol's program. + /// + /// - **Type**: `Program<'info, Wormhole>` + /// + /// ## Purpose: + /// Facilitates interactions with the Wormhole protocol, such as posting messages across chains. + /// + /// ## Security Considerations: + /// - **Program Integrity**: Ensures that interactions are only made with the legitimate Wormhole program. pub wormhole_program: Program<'info, Wormhole>, + /// The `wormhole_bridge` account holds the Wormhole bridge data. + /// + /// - **Type**: `Account<'info, wormhole::BridgeData>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`address = config.wormhole.bridge @ ErrorCode::InvalidWormholeConfig`**: Ensures that the provided `wormhole_bridge` account matches the expected bridge address stored in `config.wormhole.bridge`. + /// + /// ## Purpose: + /// Maintains bridge-specific data required for posting messages via Wormhole. + /// + /// ## Security Considerations: + /// - **Address Constraint**: Prevents unauthorized accounts from being used by enforcing that the `wormhole_bridge` matches the expected address. #[account( mut, address = config.wormhole.bridge @ ErrorCode::InvalidWormholeConfig @@ -34,6 +80,18 @@ pub struct DispatchRoot<'info> { /// be mutable. pub wormhole_bridge: Account<'info, wormhole::BridgeData>, + /// The `wormhole_fee_collector` account collects fees associated with Wormhole messages. + /// + /// - **Type**: `Account<'info, wormhole::FeeCollector>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`address = config.wormhole.fee_collector @ ErrorCode::InvalidWormholeFeeCollector`**: Ensures that the provided `wormhole_fee_collector` account matches the expected fee collector address stored in `config.wormhole.fee_collector`. + /// + /// ## Purpose: + /// Handles the collection and management of fees for Wormhole message dispatches. + /// + /// ## Security Considerations: + /// - **Address Constraint**: Prevents unauthorized accounts from being used by enforcing that the `wormhole_fee_collector` matches the expected address. #[account( mut, address = config.wormhole.fee_collector @ ErrorCode::InvalidWormholeFeeCollector @@ -42,6 +100,19 @@ pub struct DispatchRoot<'info> { /// account be mutable. pub wormhole_fee_collector: Account<'info, wormhole::FeeCollector>, + /// The `wormhole_emitter` account is the program's emitter account. + /// + /// - **Type**: `Account<'info, WormholeEmitter>` + /// - **Attributes**: + /// - **`seeds = [WormholeEmitter::SEED_PREFIX]`**: Specifies the seed used to derive the PDA for the `wormhole_emitter` account. + /// - **`bump`**: The bump seed used in conjunction with the seeds to find the PDA. + /// + /// ## Purpose: + /// Acts as the emitter responsible for generating and managing Wormhole messages. + /// + /// ## Security Considerations: + /// - **PDA Derivation**: Ensures that only the legitimate emitter account is accessed, preventing unauthorized message emissions. + /// - **Read-Only**: Not marked as mutable, indicating that it won't be modified during this instruction, enhancing security by preventing unintended state changes. #[account( seeds = [WormholeEmitter::SEED_PREFIX], bump, @@ -49,6 +120,18 @@ pub struct DispatchRoot<'info> { /// Program's emitter account. Read-only. pub wormhole_emitter: Account<'info, WormholeEmitter>, + /// The `wormhole_sequence` account tracks the sequence number for Wormhole messages. + /// + /// - **Type**: `Account<'info, wormhole::SequenceTracker>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`address = config.wormhole.sequence @ ErrorCode::InvalidWormholeSequence`**: Ensures that the provided `wormhole_sequence` account matches the expected sequence tracker address stored in `config.wormhole.sequence`. + /// + /// ## Purpose: + /// Maintains and updates the sequence number for each Wormhole message, ensuring proper ordering and uniqueness. + /// + /// ## Security Considerations: + /// - **Address Constraint**: Prevents unauthorized accounts from being used by enforcing that the `wormhole_sequence` matches the expected address. #[account( mut, address = config.wormhole.sequence @ ErrorCode::InvalidWormholeSequence @@ -57,6 +140,20 @@ pub struct DispatchRoot<'info> { /// account be mutable. pub wormhole_sequence: Account<'info, wormhole::SequenceTracker>, + /// The `wormhole_message` account represents the Wormhole message to be dispatched. + /// + /// - **Type**: `UncheckedAccount<'info>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`seeds = [SEED_PREFIX_SENT, &wormhole_sequence.next_value().to_le_bytes()[..]]`**: Specifies the seeds used to derive the PDA for the `wormhole_message` account, incorporating a dynamic component based on the sequence number. + /// - **`bump`**: The bump seed used in conjunction with the seeds to find the PDA. + /// + /// ## Purpose: + /// Holds the serialized Wormhole message that will be dispatched to the target chain. + /// + /// ## Security Considerations: + /// - **UncheckedAccount**: Since this is an `UncheckedAccount`, Anchor does not perform type or ownership checks. It is crucial to manually validate that this account is correctly derived and holds valid message data. + /// - **Address Constraint**: Ensures that the `wormhole_message` account is uniquely derived based on the current sequence number, preventing message duplication or replay. #[account( mut, seeds = [ @@ -69,19 +166,56 @@ pub struct DispatchRoot<'info> { /// account be mutable. pub wormhole_message: UncheckedAccount<'info>, - /// CHECK: Snapshotter program + /// The `snapshotter_config` account represents the snapshotter's configuration. + /// + /// - **Type**: `UncheckedAccount<'info>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`address = config.snapshotter_config @ ErrorCode::InvalidSnapshotterConfig`**: Ensures that the provided `snapshotter_config` account matches the expected snapshotter configuration address stored in `config.snapshotter_config`. + /// + /// ## Purpose: + /// Maintains the snapshotter's configuration, ensuring that dispatch operations are consistent with the current configuration. + /// + /// ## Security Considerations: + /// - **Address Constraint**: Enforces that the `snapshotter_config` account provided is the one expected by the `config` account, preventing unauthorized modifications. + /// - **UncheckedAccount**: Requires manual validation to ensure that the account's data aligns with program expectations. #[account( mut, address = config.snapshotter_config @ ErrorCode::InvalidSnapshotterConfig )] + /// CHECK: Snapshotter program pub snapshotter_config: UncheckedAccount<'info>, - /// System program. + /// The `system_program` is the Solana System Program responsible for creating and allocating accounts. + /// + /// - **Type**: `Program<'info, System>` + /// + /// ## Purpose: + /// Facilitates interactions with the Solana runtime, such as account creation, funding, and lamport transfers. + /// + /// ## Security Considerations: + /// - **Standardization**: By referencing the standard System Program, the program ensures compatibility and reliability in account management operations. pub system_program: Program<'info, System>, - /// Clock sysvar. + /// The `clock` sysvar provides access to the Solana cluster's clock data. + /// + /// - **Type**: `Sysvar<'info, Clock>` + /// + /// ## Purpose: + /// Allows the program to access time-related data, such as the current slot, epoch, and unix timestamp. + /// + /// ## Security Considerations: + /// - **Immutable**: Sysvars like `Clock` are read-only, ensuring that programs cannot tamper with time data. pub clock: Sysvar<'info, Clock>, - /// Rent sysvar. + /// The `rent` sysvar provides access to the rent-related data of the Solana cluster. + /// + /// - **Type**: `Sysvar<'info, Rent>` + /// + /// ## Purpose: + /// Allows the program to query rent rates and determine whether an account is rent-exempt. + /// + /// ## Security Considerations: + /// - **Immutable**: Sysvars like `Rent` are read-only, ensuring that programs cannot tamper with rent data. pub rent: Sysvar<'info, Rent>, } diff --git a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs index dbcec6b3..c98bc05c 100644 --- a/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs +++ b/packages/solana/programs/wormhole-reporter/src/contexts/initialize.rs @@ -8,38 +8,110 @@ pub const SEED_PREFIX_SENT: &[u8; 4] = b"sent"; #[derive(Accounts)] pub struct Initialize<'info> { + /// The `owner` is a Signer account, indicating that whoever calls this instruction + /// must sign the transaction with their private key. This ensures that the initializer + /// has authority. + /// + /// `#[account(mut)]` is used here because the `owner` account's lamports are used + /// to fund the creation of the `config` and `wormhole_emitter` accounts. + /// + /// ## Attributes + /// + /// - **`mut`**: Marks the `owner` account as mutable, allowing its lamports to be debited. #[account(mut)] /// Whoever initializes the config will be the owner of the program. Signer /// for creating the [`Config`] account and posting a Wormhole message /// indicating that the program is alive. pub owner: Signer<'info>, + /// The `config` account will be created (initialized) by this instruction. + /// + /// The `init` attribute indicates that this account should be created (allocated and assigned) + /// and initialized with the given seeds, bump, and space. + /// + /// - **`payer = owner`**: The `owner` account pays for the rent and creation cost of this account. + /// - **`seeds = [Config::SEED_PREFIX]`**: Sets the PDA (program-derived address) seed that + /// uniquely identifies the `config` account. This ensures that the correct PDA is referenced. + /// - **`bump`**: Used in combination with the seeds to find the PDA. The `bump` ensures a valid PDA + /// that is not already taken by another account. + /// - **`space = Config::MAXIMUM_SIZE`**: Allocates the appropriate amount of space for the `config` account's data based on the `Config` structure. + /// + /// ## Attributes + /// + /// - **`init`**: Indicates that this account should be initialized by the instruction. + /// - **`payer = owner`**: Specifies that the `owner` account will pay for the account's rent and creation. + /// - **`seeds = [Config::SEED_PREFIX]`**: Defines the seed used to derive the PDA for the `config` account. + /// - **`bump`**: Provides the bump seed necessary for PDA derivation. + /// - **`space = Config::MAXIMUM_SIZE`**: Allocates sufficient space for the `config` account's data. + /// + /// ## Purpose: + /// Acts as the central configuration hub, storing essential data required for dispatching roots, + /// managing subscriptions, and maintaining program integrity. + /// + /// ## Security Considerations: + /// - **PDA Derivation**: Ensures that the correct `config` account is accessed, preventing unauthorized access. + /// - **Read-Only**: Not marked as mutable, indicating that it won't be modified during this instruction, enhancing security by preventing unintended state changes. #[account( init, payer = owner, seeds = [Config::SEED_PREFIX], bump, space = Config::MAXIMUM_SIZE, - )] /// Config account, which saves program data useful for other instructions. /// Also saves the payer of the [`initialize`](crate::initialize) instruction /// as the program's owner. pub config: Account<'info, Config>, - /// Wormhole program. + /// The `wormhole_program` is the Wormhole protocol's program. + /// + /// - **Type**: `Program<'info, Wormhole>` + /// + /// ## Purpose: + /// Facilitates interactions with the Wormhole protocol, such as posting messages across chains. + /// + /// ## Security Considerations: + /// - **Program Integrity**: Ensures that interactions are only made with the legitimate Wormhole program. pub wormhole_program: Program<'info, Wormhole>, + /// The `wormhole_bridge` account holds the Wormhole bridge data. + /// + /// - **Type**: `Account<'info, wormhole::BridgeData>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`seeds = [wormhole::BridgeData::SEED_PREFIX]`**: Specifies the seed used to derive the PDA for the `wormhole_bridge` account. + /// - **`bump`**: The bump seed used in conjunction with the seeds to find the PDA. + /// - **`seeds::program = wormhole_program.key`**: Ensures that the PDA is derived using the Wormhole program's ID, preventing cross-program address collisions. + /// + /// ## Purpose: + /// Maintains bridge-specific data required for posting messages via Wormhole. + /// + /// ## Security Considerations: + /// - **Address Constraint**: Prevents unauthorized or incorrect bridge accounts from being used, ensuring that messages are routed through the legitimate bridge. #[account( mut, seeds = [wormhole::BridgeData::SEED_PREFIX], bump, - seeds::program = wormhole_program.key, + seeds::program = wormhole_program.key )] /// Wormhole bridge data account (a.k.a. its config). /// [`wormhole::post_message`] requires this account be mutable. pub wormhole_bridge: Account<'info, wormhole::BridgeData>, + /// The `wormhole_fee_collector` account collects fees associated with Wormhole messages. + /// + /// - **Type**: `Account<'info, wormhole::FeeCollector>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`seeds = [wormhole::FeeCollector::SEED_PREFIX]`**: Specifies the seed used to derive the PDA for the `wormhole_fee_collector` account. + /// - **`bump`**: The bump seed used in conjunction with the seeds to find the PDA. + /// - **`seeds::program = wormhole_program.key`**: Ensures that the PDA is derived using the Wormhole program's ID, preventing cross-program address collisions. + /// + /// ## Purpose: + /// Handles the collection and management of fees for Wormhole message dispatches. + /// + /// ## Security Considerations: + /// - **Address Constraint**: Prevents unauthorized accounts from intercepting or mismanaging fees by enforcing that the `wormhole_fee_collector` matches the expected address. #[account( mut, seeds = [wormhole::FeeCollector::SEED_PREFIX], @@ -51,6 +123,22 @@ pub struct Initialize<'info> { /// [`wormhole::post_message`] requires this account be mutable. pub wormhole_fee_collector: Account<'info, wormhole::FeeCollector>, + /// The `wormhole_emitter` account is the program's emitter account. + /// + /// - **Type**: `Account<'info, WormholeEmitter>` + /// - **Attributes**: + /// - **`init`**: Specifies that this account should be initialized (allocated and assigned) by this instruction. + /// - **`payer = owner`**: The `owner` account will pay for the rent and creation costs of the `wormhole_emitter` account. + /// - **`seeds = [WormholeEmitter::SEED_PREFIX]`**: Defines the seed used to derive the PDA for the `wormhole_emitter` account. + /// - **`bump`**: The bump seed used in conjunction with the seeds to find the PDA. + /// - **`space = WormholeEmitter::MAXIMUM_SIZE`**: Allocates sufficient space for the `wormhole_emitter` account's data based on the `WormholeEmitter` structure's maximum size. + /// + /// ## Purpose: + /// Serves as the emitter responsible for generating and managing Wormhole messages. + /// + /// ## Security Considerations: + /// - **PDA Derivation**: Ensures that only the legitimate emitter account is accessed, preventing unauthorized message emissions. + /// - **Read-Only Access**: Not marked as mutable, preventing unintended state changes and enhancing security. #[account( init, payer = owner, @@ -63,6 +151,21 @@ pub struct Initialize<'info> { /// [`wormhole::post_message`] only needs it to be read-only. pub wormhole_emitter: Account<'info, WormholeEmitter>, + /// The `wormhole_sequence` account tracks the sequence number for Wormhole messages. + /// + /// - **Type**: `UncheckedAccount<'info>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`seeds = [wormhole::SequenceTracker::SEED_PREFIX, wormhole_emitter.key().as_ref()]`**: Specifies the seeds used to derive the PDA for the `wormhole_sequence` account, incorporating the emitter's public key to ensure uniqueness. + /// - **`bump`**: The bump seed used in conjunction with the seeds to find the PDA. + /// - **`seeds::program = wormhole_program.key`**: Ensures that the PDA is derived using the Wormhole program's ID, preventing cross-program address collisions. + /// + /// ## Purpose: + /// Maintains and updates the sequence number for each Wormhole message, ensuring proper ordering and uniqueness. + /// + /// ## Security Considerations: + /// - **Address Constraint**: Enforces that the `wormhole_sequence` account matches the expected address stored in `config.wormhole.sequence`. + /// - **UncheckedAccount**: Since this is an `UncheckedAccount`, Anchor does not perform type or ownership checks. It is crucial to manually validate that this account is correctly derived and holds valid sequence data. #[account( mut, seeds = [ @@ -78,6 +181,20 @@ pub struct Initialize<'info> { /// [`wormhole::post_message`] requires this account be mutable. pub wormhole_sequence: UncheckedAccount<'info>, + /// The `wormhole_message` account represents the Wormhole message to be dispatched. + /// + /// - **Type**: `UncheckedAccount<'info>` + /// - **Attributes**: + /// - **`mut`**: Indicates that the account may be mutated during the instruction. + /// - **`seeds = [SEED_PREFIX_SENT, &wormhole::INITIAL_SEQUENCE.to_le_bytes()[..]]`**: Specifies the seeds used to derive the PDA for the `wormhole_message` account, incorporating a static initial sequence to ensure uniqueness. + /// - **`bump`**: The bump seed used in conjunction with the seeds to find the PDA. + /// + /// ## Purpose: + /// Holds the serialized Wormhole message that will be dispatched to the target chain. + /// + /// ## Security Considerations: + /// - **UncheckedAccount**: Since this is an `UncheckedAccount`, Anchor does not perform type or ownership checks. It is crucial to manually validate that this account is correctly derived and holds valid message data. + /// - **Address Derivation**: Incorporating a static initial sequence ensures that each message account is uniquely derived, preventing address collisions and replay attacks. #[account( mut, seeds = [ @@ -91,15 +208,49 @@ pub struct Initialize<'info> { /// [`wormhole::post_message`] requires this account be mutable. pub wormhole_message: UncheckedAccount<'info>, + /// The `snapshotter_config` account represents the snapshotter's configuration. + /// + /// - **Type**: `UncheckedAccount<'info>` + /// + /// ## Purpose: + /// Maintains the snapshotter's configuration, ensuring that dispatch operations are consistent with the current configuration. + /// + /// ## Security Considerations: + /// - **Address Constraint**: Enforces that the `snapshotter_config` account provided is the one expected by the `config` account, preventing unauthorized modifications. + /// - **UncheckedAccount**: Requires manual validation to ensure that the account's data aligns with program expectations. /// CHECK: Snapshotter program pub snapshotter_config: UncheckedAccount<'info>, - /// Clock sysvar. + /// The `clock` sysvar provides access to the Solana cluster's clock data. + /// + /// - **Type**: `Sysvar<'info, Clock>` + /// + /// ## Purpose: + /// Allows the program to access time-related data, such as the current slot, epoch, and Unix timestamp. + /// + /// ## Security Considerations: + /// - **Immutable**: Sysvars like `Clock` are read-only, ensuring that programs cannot tamper with time data. pub clock: Sysvar<'info, Clock>, - /// Rent sysvar. + /// The `rent` sysvar provides access to the rent-related data of the Solana cluster. + /// + /// - **Type**: `Sysvar<'info, Rent>` + /// + /// ## Purpose: + /// Allows the program to query rent rates and determine whether an account is rent-exempt. + /// + /// ## Security Considerations: + /// - **Immutable**: Sysvars like `Rent` are read-only, ensuring that programs cannot tamper with rent data. pub rent: Sysvar<'info, Rent>, - /// System program. + /// The `system_program` is the Solana System Program responsible for creating and allocating accounts. + /// + /// - **Type**: `Program<'info, System>` + /// + /// ## Purpose: + /// Facilitates interactions with the Solana runtime, such as creating and funding accounts. + /// + /// ## Security Considerations: + /// - **Standardization**: By referencing the standard System Program, the program ensures compatibility and reliability in account management operations. pub system_program: Program<'info, System>, } diff --git a/packages/solana/programs/wormhole-reporter/src/state/config.rs b/packages/solana/programs/wormhole-reporter/src/state/config.rs index 2e4df0bb..bbef4d73 100644 --- a/packages/solana/programs/wormhole-reporter/src/state/config.rs +++ b/packages/solana/programs/wormhole-reporter/src/state/config.rs @@ -1,19 +1,35 @@ use anchor_lang::prelude::*; #[derive(Default, AnchorSerialize, AnchorDeserialize, Clone, PartialEq, Eq)] -/// Wormhole program related addresses. pub struct WormholeAddresses { /// [BridgeData](wormhole_anchor_sdk::wormhole::BridgeData) address. + /// + /// The BridgeData account holds configuration and state information necessary + /// for the Wormhole bridge operations. pub bridge: Pubkey, + /// [FeeCollector](wormhole_anchor_sdk::wormhole::FeeCollector) address. + /// + /// The FeeCollector account is responsible for accumulating fees associated + /// with Wormhole message dispatches. It ensures that the program can cover + /// the costs of cross-chain messaging. pub fee_collector: Pubkey, + /// [SequenceTracker](wormhole_anchor_sdk::wormhole::SequenceTracker) address. + /// + /// The SequenceTracker account maintains the sequence number for Wormhole messages, + /// ensuring proper ordering and uniqueness. It is crucial for preventing replay + /// attacks and maintaining message integrity. pub sequence: Pubkey, } impl WormholeAddresses { + /// The total length of the `WormholeAddresses` structure in bytes. + /// + /// This constant is used to allocate sufficient space for the `WormholeAddresses` + /// within other account structures, such as `Config`. pub const LEN: usize = - 32 // config + 32 // bridge + 32 // fee_collector + 32 // sequence ; @@ -21,31 +37,59 @@ impl WormholeAddresses { #[account] #[derive(Default)] -/// Config account data. pub struct Config { /// Program's owner. + /// + /// The `owner` field holds the public key of the entity that owns the program. + /// This account is typically the signer who initializes the program and has administrative + /// privileges over its operations. pub owner: Pubkey, + /// Wormhole program's relevant addresses. + /// + /// The `wormhole` field contains a `WormholeAddresses` structure, which encapsulates + /// all necessary Wormhole-related public keys required for cross-chain messaging. pub wormhole: WormholeAddresses, - /// AKA nonce. Just zero, but saving this information in this account - /// anyway. + + /// Batch identifier. + /// + /// The `batch_id` serves as an identifier for batches of operations or messages. + /// It can be used to group related actions or track the program's state across different + /// operational phases. pub batch_id: u32, - /// AKA consistency level. u8 representation of Solana's - /// [Finality](wormhole_anchor_sdk::wormhole::Finality). + + /// Finality level. + /// + /// The `finality` field represents the consistency level for Solana transactions, + /// typically corresponding to Solana's [Finality](wormhole_anchor_sdk::wormhole::Finality) + /// enum. It determines how finalized a transaction should be before it's considered + /// complete or irreversible. pub finality: u8, - /// Snapshotter config address. - pub snapshotter_config: Pubkey + + /// Snapshotter configuration address. + /// + /// The `snapshotter_config` holds the public key of the Snapshotter program's configuration + /// account. This allows the program to interact with the Snapshotter for maintaining + /// consistent states or snapshots of data as required. + pub snapshotter_config: Pubkey, } impl Config { - pub const MAXIMUM_SIZE: usize = 8 // discriminator + /// The maximum size of the `Config` account in bytes. + /// + /// This constant ensures that the `Config` account has enough allocated space to store + /// all its fields, including the discriminator used by Anchor. + pub const MAXIMUM_SIZE: usize = 8 // Discriminator + 32 // owner - + WormholeAddresses::LEN + + WormholeAddresses::LEN // wormhole + 4 // batch_id + 1 // finality + 32 // snapshotter_config - ; - /// AKA `b"config"`. + + /// The seed prefix used for deriving the PDA (Program Derived Address) of the `Config` account. + /// + /// Using a consistent seed prefix ensures that the `Config` account can be reliably + /// derived and accessed across different instructions and transactions. pub const SEED_PREFIX: &'static [u8; 6] = b"config"; -} \ No newline at end of file +} diff --git a/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs b/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs index 28729c0b..805f603c 100644 --- a/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs +++ b/packages/solana/programs/wormhole-reporter/src/state/wormhole_emitter.rs @@ -3,17 +3,23 @@ use wormhole_anchor_sdk::wormhole; #[account] #[derive(Default)] -/// Wormhole emitter account. pub struct WormholeEmitter { /// PDA bump. pub bump: u8, } impl WormholeEmitter { - pub const MAXIMUM_SIZE: usize = 8 // discriminator - + 1 // bump - ; - /// AKA `b"emitter` (see - /// [`SEED_PREFIX_EMITTER`](wormhole::SEED_PREFIX_EMITTER)). + /// The maximum size of the `WormholeEmitter` account in bytes. + /// + /// This constant ensures that the account has enough allocated space to store + /// all its fields, including the discriminator used by Anchor. + pub const MAXIMUM_SIZE: usize = 8 // Discriminator (Anchor) + + 1 // bump + ; + + /// The seed prefix used for deriving the PDA (Program Derived Address) of the `WormholeEmitter` account. + /// + /// Using a consistent seed prefix ensures that the `WormholeEmitter` account can be reliably + /// derived and accessed across different instructions and transactions. pub const SEED_PREFIX: &'static [u8; 7] = wormhole::SEED_PREFIX_EMITTER; } From f4da53dd27ebc01fe6f1ee1e490a2ab469e2f02b Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 18 Dec 2024 13:51:26 +0100 Subject: [PATCH 25/31] refactor(solana): rn MerkleMountainRange into BatchMerkleTree --- .../solana/programs/snapshotter/src/lib.rs | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/solana/programs/snapshotter/src/lib.rs b/packages/solana/programs/snapshotter/src/lib.rs index 8035d439..5ac04e81 100644 --- a/packages/solana/programs/snapshotter/src/lib.rs +++ b/packages/solana/programs/snapshotter/src/lib.rs @@ -104,7 +104,7 @@ pub mod snapshotter { // but the last batch. For the last batch, it can be fewer accounts. // 3. If it's the last batch, finalize the root and reset `expected_batch` to 0; // otherwise, increment `expected_batch` and mark the root as not finalized. - // 4. Hash each account's state and update the Merkle Mountain Range (MMR) root. + // 4. Hash each account's state and update the Batch Merkle Tree (BMT) root. // 5. Store the updated root in the `config`. pub fn calculate_root(ctx: Context, batch: u64) -> Result<()> { let config = &mut ctx.accounts.config; @@ -160,35 +160,35 @@ pub mod snapshotter { )); } - // Step 5: Update the Merkle Mountain Range (MMR) with the new account hashes - let mut mmr = MerkleMountainRange::from(Hash::new_from_array(config.root)); - mmr.update_root(account_hashes)?; + // Step 5: Update the Batch Merkle Tree (BMT) with the new account hashes + let mut tree = BatchMerkleTree::from(Hash::new_from_array(config.root)); + tree.push_batch_of_leaves(account_hashes)?; // Store the updated root back into the `Config` - config.root = mmr.root.to_bytes(); + config.root = tree.root.to_bytes(); Ok(()) } } -pub struct MerkleMountainRange { +pub struct BatchMerkleTree { pub root: Hash, } -impl From for MerkleMountainRange { +impl From for BatchMerkleTree { fn from(root: Hash) -> Self { - MerkleMountainRange { root: root } + BatchMerkleTree { root: root } } } -impl MerkleMountainRange { +impl BatchMerkleTree { pub fn new() -> Self { - MerkleMountainRange { + BatchMerkleTree { root: Hash::default(), } } - pub fn update_root(&mut self, new_leaves: Vec) -> Result<()> { - let mut current_layer = new_leaves; + pub fn push_batch_of_leaves(&mut self, leaves: Vec) -> Result<()> { + let mut current_layer = leaves; while current_layer.len() > 1 { let mut next_layer = Vec::new(); @@ -201,7 +201,6 @@ impl MerkleMountainRange { ])); i += 2; } else { - // If there's an odd one out, it becomes a peak as-is next_layer.push(current_layer[i]); i += 1; } From 863fb42ca03b563fb611f843f0ee747b6a8f3b06 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 18 Dec 2024 20:19:05 +0100 Subject: [PATCH 26/31] refactor(solana): rn push_batch_of_leaves into push_batch --- packages/solana/programs/snapshotter/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/solana/programs/snapshotter/src/lib.rs b/packages/solana/programs/snapshotter/src/lib.rs index 5ac04e81..982aea3c 100644 --- a/packages/solana/programs/snapshotter/src/lib.rs +++ b/packages/solana/programs/snapshotter/src/lib.rs @@ -1,5 +1,5 @@ use anchor_lang::prelude::*; -use anchor_lang::solana_program::keccak::{hashv, Hash}; +use anchor_lang::solana_program::hash::{hashv, Hash}; declare_id!("37298hWBczA1od9ytwgSYyhP42WLNiXieAVCxBxAeX9S"); @@ -162,7 +162,7 @@ pub mod snapshotter { // Step 5: Update the Batch Merkle Tree (BMT) with the new account hashes let mut tree = BatchMerkleTree::from(Hash::new_from_array(config.root)); - tree.push_batch_of_leaves(account_hashes)?; + tree.push_batch(account_hashes)?; // Store the updated root back into the `Config` config.root = tree.root.to_bytes(); @@ -187,7 +187,7 @@ impl BatchMerkleTree { } } - pub fn push_batch_of_leaves(&mut self, leaves: Vec) -> Result<()> { + pub fn push_batch(&mut self, leaves: Vec) -> Result<()> { let mut current_layer = leaves; while current_layer.len() > 1 { From 97f60915b9741f87a3edeaf83108a5c41e8a78ac Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Thu, 19 Dec 2024 14:16:53 +0100 Subject: [PATCH 27/31] refactor(solana): creates utils folder within tests --- packages/solana/tests/{utils.ts => utils/index.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/solana/tests/{utils.ts => utils/index.ts} (100%) diff --git a/packages/solana/tests/utils.ts b/packages/solana/tests/utils/index.ts similarity index 100% rename from packages/solana/tests/utils.ts rename to packages/solana/tests/utils/index.ts From 79ac5b8e8d6eb96f39ffd36d31a3ddbebf92bd5d Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Thu, 19 Dec 2024 19:21:54 +0100 Subject: [PATCH 28/31] feat(evm): adds verifyForeignSolanaAccount within HashiProver --- .../contracts/libraries/BatchMerkleTree.sol | 59 +++++ packages/evm/contracts/prover/HashiProver.sol | 19 +- .../evm/contracts/prover/HashiProverLib.sol | 27 ++- .../contracts/prover/HashiProverStructs.sol | 7 + .../prover/HashiProverUpgradeable.sol | 19 +- .../evm/contracts/test/HashiProverTest.sol | 4 + .../test/HashiProverTestUpgradeable.sol | 4 + packages/evm/test/05_HashiProver.spec.ts | 41 ++++ packages/evm/test/utils/batch-merkle-tree.ts | 218 ++++++++++++++++++ 9 files changed, 395 insertions(+), 3 deletions(-) create mode 100644 packages/evm/contracts/libraries/BatchMerkleTree.sol create mode 100644 packages/evm/test/utils/batch-merkle-tree.ts diff --git a/packages/evm/contracts/libraries/BatchMerkleTree.sol b/packages/evm/contracts/libraries/BatchMerkleTree.sol new file mode 100644 index 00000000..3f50c1a2 --- /dev/null +++ b/packages/evm/contracts/libraries/BatchMerkleTree.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.0; + +library BatchMerkleTree { + error InvalidNodeLength(); + error InvalidPosition(); + error InvalidNodeExpected33Bytes(); + + function verify(bytes[][] calldata proof, bytes32 targetNode, bytes32 root) internal pure returns (bool) { + bytes[] memory batchProof; + for (uint256 i = 0; i < proof.length; i++) { + if (proof[i].length != 1) { + batchProof = proof[i]; + } + } + + bytes32 batchRoot = targetNode; + for (uint256 i = 0; i < batchProof.length; i++) { + bytes memory node = batchProof[i]; + + if (node.length != 33) revert InvalidNodeLength(); + uint8 position = uint8(node[32]); + if (position != 1 && position != 2) revert InvalidPosition(); + bytes32 data = bytes32(node); + + bool isLeftNode = position == 1; + batchRoot = isLeftNode ? hashNodes(data, batchRoot) : hashNodes(batchRoot, data); + } + + bytes32[] memory batchRoots = new bytes32[](proof.length); + for (uint256 i = 0; i < proof.length; i++) { + bytes[] memory batch = proof[i]; + // targetNode is the onlyElement in this batch + if (batch.length == 0) + batchRoots[i] = targetNode; + // batch that contains only the root + else if (batch.length == 1) { + bytes memory batchRootNode = batch[0]; + if (batchRootNode.length != 33) revert InvalidNodeExpected33Bytes(); + uint8 position = uint8(batchRootNode[32]); + if (position != 0) revert InvalidPosition(); + batchRoots[i] = bytes32(batchRootNode); + } else { + batchRoots[i] = batchRoot; + } + } + + bytes32 calculatedRoot = batchRoots.length > 1 ? hashNodes(batchRoots[0], batchRoots[1]) : batchRoots[0]; + for (uint256 i = 2; i < batchRoots.length; i++) { + calculatedRoot = hashNodes(calculatedRoot, batchRoots[i]); + } + + return calculatedRoot == root; + } + + function hashNodes(bytes32 node1, bytes32 node2) internal pure returns (bytes32) { + return sha256(abi.encodePacked(node1, node2)); + } +} diff --git a/packages/evm/contracts/prover/HashiProver.sol b/packages/evm/contracts/prover/HashiProver.sol index a8db5f18..0d0fe3e1 100644 --- a/packages/evm/contracts/prover/HashiProver.sol +++ b/packages/evm/contracts/prover/HashiProver.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import { HashiProverLib } from "./HashiProverLib.sol"; -import { AccountAndStorageProof, ReceiptProof } from "./HashiProverStructs.sol"; +import { AccountAndStorageProof, ReceiptProof, SolanaAccountProof } from "./HashiProverStructs.sol"; contract HashiProver { /// @notice Stores the address of the ShoyuBashi contract. @@ -50,4 +50,21 @@ contract HashiProver { function verifyForeignStorage(AccountAndStorageProof calldata proof) internal view returns (bytes[] memory) { return HashiProverLib.verifyForeignStorage(proof, SHOYU_BASHI); } + + /** + * @dev Verifies the data of a Solana account against the merkle root generated by the Snapshotter + * on Solana and propagated using Hashi. + * + * @param proof A `SolanaAccountProof` struct containing proof details: + * - chainId: The chain ID of the foreign Solana based blockchain where the account resides. + * - nonce: A unique identifier used to locate the specific Merkle root in Hashi against which the proof verification is performed. + * - account: The Solana account data with this format: pubkey, lamports, data, owner, rent_epoch + * - accountProof: A Batch Merkle proof to validate the existence of the account + * in the state of the foreign blockchain. + * + * @return bytes The serialized Solana account data if the verification succeeds. + */ + function verifyForeignSolanaAccount(SolanaAccountProof calldata proof) internal view returns (bytes memory) { + return HashiProverLib.verifyForeignSolanaAccount(proof, SHOYU_BASHI); + } } diff --git a/packages/evm/contracts/prover/HashiProverLib.sol b/packages/evm/contracts/prover/HashiProverLib.sol index e3945916..acd86905 100644 --- a/packages/evm/contracts/prover/HashiProverLib.sol +++ b/packages/evm/contracts/prover/HashiProverLib.sol @@ -4,7 +4,8 @@ pragma solidity ^0.8.0; import { SecureMerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol"; import { MerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/MerkleTrie.sol"; import { RLPReader } from "@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol"; -import { AccountAndStorageProof, ReceiptProof } from "./HashiProverStructs.sol"; +import { AccountAndStorageProof, ReceiptProof, SolanaAccountProof } from "./HashiProverStructs.sol"; +import { BatchMerkleTree } from "../libraries/BatchMerkleTree.sol"; import { IShoyuBashi } from "../interfaces/IShoyuBashi.sol"; library HashiProverLib { @@ -19,6 +20,7 @@ library HashiProverLib { error InvalidStorageHash(); error InvalidStorageProofParams(); error UnsupportedTxType(); + error InvalidAccountProof(); /** * @dev Verifies and retrieves a specific event from a transaction receipt in a foreign blockchain. @@ -92,6 +94,29 @@ library HashiProverLib { return verifyStorageProof(storageHash, proof.storageKeys, proof.storageProof); } + /** + * @dev Verifies the data of a Solana account against the merkle root generated by the Snapshotter + * on Solana and propagated using Hashi. + * + * @param proof A `SolanaAccountProof` struct containing proof details: + * - chainId: The chain ID of the foreign Solana based blockchain where the account resides. + * - nonce: A unique identifier used to locate the specific Merkle root in Hashi against which the proof verification is performed. + * - account: The Solana account data with this format: pubkey, lamports, data, owner, rent_epoch + * - accountProof: A Batch Merkle proof to validate the existence of the account + * in the state of the foreign blockchain. + * @param shoyuBashi The address of ShoyuBashi contract + * + * @return bytes The serialized Solana account data if the verification succeeds. + */ + function verifyForeignSolanaAccount( + SolanaAccountProof calldata proof, + address shoyuBashi + ) internal view returns (bytes memory) { + bytes32 root = IShoyuBashi(shoyuBashi).getThresholdHash(proof.chainId, proof.nonce); + if (!BatchMerkleTree.verify(proof.accountProof, sha256(proof.account), root)) revert InvalidAccountProof(); + return proof.account; + } + /** * @notice Verifies a block header against the Hashi contract by checking its hash and, if needed, traversing ancestral blocks. * @dev This function first checks if the provided block header hash matches the threshold hash stored in the ShoyuBashi contract. diff --git a/packages/evm/contracts/prover/HashiProverStructs.sol b/packages/evm/contracts/prover/HashiProverStructs.sol index 3b0e7f78..3a9f6f3a 100644 --- a/packages/evm/contracts/prover/HashiProverStructs.sol +++ b/packages/evm/contracts/prover/HashiProverStructs.sol @@ -31,3 +31,10 @@ struct ReceiptProof { bytes transactionIndex; // The index of the transaction within the block's transaction list (RLP-encoded). uint256 logIndex; // The index of the log entry within the transaction receipt being proven. } + +struct SolanaAccountProof { + uint256 chainId; // The ID of the blockchain where the proof is applicable. + uint256 nonce; // A unique identifier used to locate the specific Merkle root in Hashi for which the proof verification is performed. + bytes account; // The Solana account data with this format: pubkey, lamports, data, owner, rent_epoch + bytes[][] accountProof; // Merkle proof to verify the accunt within the merkle root stored in Hashi +} diff --git a/packages/evm/contracts/prover/HashiProverUpgradeable.sol b/packages/evm/contracts/prover/HashiProverUpgradeable.sol index 9ab2ede9..9300307c 100644 --- a/packages/evm/contracts/prover/HashiProverUpgradeable.sol +++ b/packages/evm/contracts/prover/HashiProverUpgradeable.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { HashiProverLib } from "./HashiProverLib.sol"; -import { AccountAndStorageProof, ReceiptProof } from "./HashiProverStructs.sol"; +import { AccountAndStorageProof, ReceiptProof, SolanaAccountProof } from "./HashiProverStructs.sol"; contract HashiProverUpgradeable is Initializable, OwnableUpgradeable { /// @notice Stores the address of the ShoyuBashi contract. @@ -73,6 +73,23 @@ contract HashiProverUpgradeable is Initializable, OwnableUpgradeable { return HashiProverLib.verifyForeignStorage(proof, shoyuBashi); } + /** + * @dev Verifies the data of a Solana account against the merkle root generated by the Snapshotter + * on Solana and propagated using Hashi. + * + * @param proof A `SolanaAccountProof` struct containing proof details: + * - chainId: The chain ID of the foreign Solana based blockchain where the account resides. + * - nonce: A unique identifier used to locate the specific Merkle root in Hashi against which the proof verification is performed. + * - account: The Solana account data with this format: pubkey, lamports, data, owner, rent_epoch + * - accountProof: A Batch Merkle proof to validate the existence of the account + * in the state of the foreign blockchain. + * + * @return bytes The serialized Solana account data if the verification succeeds. + */ + function verifyForeignSolanaAccount(SolanaAccountProof calldata proof) internal view returns (bytes memory) { + return HashiProverLib.verifyForeignSolanaAccount(proof, shoyuBashi); + } + /// @notice This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)). uint256[49] private __gap; } diff --git a/packages/evm/contracts/test/HashiProverTest.sol b/packages/evm/contracts/test/HashiProverTest.sol index 295b2121..328886e3 100644 --- a/packages/evm/contracts/test/HashiProverTest.sol +++ b/packages/evm/contracts/test/HashiProverTest.sol @@ -14,4 +14,8 @@ contract HashiProverTest is HashiProver { function getEventValues(ReceiptProof calldata proof) external view returns (bytes memory) { return verifyForeignEvent(proof); } + + function getSolanaAccount(SolanaAccountProof calldata proof) external view returns (bytes memory) { + return verifyForeignSolanaAccount(proof); + } } diff --git a/packages/evm/contracts/test/HashiProverTestUpgradeable.sol b/packages/evm/contracts/test/HashiProverTestUpgradeable.sol index 440772e5..db7df202 100644 --- a/packages/evm/contracts/test/HashiProverTestUpgradeable.sol +++ b/packages/evm/contracts/test/HashiProverTestUpgradeable.sol @@ -19,5 +19,9 @@ contract HashiProverTestUpgradeable is UUPSUpgradeable, HashiProverUpgradeable { return verifyForeignEvent(proof); } + function getSolanaAccount(SolanaAccountProof calldata proof) external view returns (bytes memory) { + return verifyForeignSolanaAccount(proof); + } + function _authorizeUpgrade(address) internal override {} } diff --git a/packages/evm/test/05_HashiProver.spec.ts b/packages/evm/test/05_HashiProver.spec.ts index 02efc252..b8f8a41c 100644 --- a/packages/evm/test/05_HashiProver.spec.ts +++ b/packages/evm/test/05_HashiProver.spec.ts @@ -9,8 +9,11 @@ import { RECEIPT_PROOF, RECEIPT_PROOF_WITH_ANCESTRAL_BLOCKS, } from "./proofs" +import { createHash, randomBytes } from "crypto" +import BatchMerkleTree from "./utils/batch-merkle-tree" const SOURCE_CHAIN_ID = 10 +const SOLANA_CHAIN_ID = 999 let hashi: Contract, adapter: Contract, shoyuBashi: Contract, hashiProvers: Contract[], owner: SignerWithAddress @@ -37,6 +40,7 @@ describe("HashiProver", () => { ) await shoyuBashi.enableAdapters(SOURCE_CHAIN_ID, [adapter.address], 1) + await shoyuBashi.enableAdapters(SOLANA_CHAIN_ID, [adapter.address], 1) }) it("should't be able to get the value if the block is not available", async () => { @@ -217,4 +221,41 @@ describe("HashiProver", () => { ) } }) + + it("should be able to read a solana account", async () => { + // NOTE: this simulates random + /** + * hashv(&[ + pubkey.as_ref(), + &lamports.to_le_bytes(), + data, + owner.as_ref(), + &rent_epoch.to_le_bytes(), + ]) + */ + const fakeAccountData = Array.from(Array(25).keys()).map(() => randomBytes(64)) + const fakeAccountDataHashes = fakeAccountData.map((_accHash) => { + const hash = createHash("sha-256") + hash.update(_accHash) + return hash.digest() + }) + + const tree = new BatchMerkleTree() + tree.pushBatch(fakeAccountDataHashes.slice(0, 10)) + tree.pushBatch(fakeAccountDataHashes.slice(10, 20)) + tree.pushBatch(fakeAccountDataHashes.slice(20, 21)) + const targetAccountHash = fakeAccountDataHashes[20] + const targetAccount = fakeAccountData[20] + const proof = tree.getHexProof(targetAccountHash) + + const sourceChainId = 999 + const nonce = 0 + await adapter.setHashes(sourceChainId, [nonce], [tree.root()]) + + for (const hashiProver of hashiProvers) { + expect(await hashiProver.getSolanaAccount([sourceChainId, nonce, targetAccount, proof])).to.be.eq( + "0x" + targetAccount.toString("hex"), + ) + } + }) }) diff --git a/packages/evm/test/utils/batch-merkle-tree.ts b/packages/evm/test/utils/batch-merkle-tree.ts new file mode 100644 index 00000000..cec25f12 --- /dev/null +++ b/packages/evm/test/utils/batch-merkle-tree.ts @@ -0,0 +1,218 @@ +import crypto from "crypto" + +type Proof = Node[][] +type HexProof = `0x${string}`[][] + +interface Node { + data: Buffer + position: "left" | "right" | null +} + +class BatchMerkleTree { + private _batches: Buffer[][] + + constructor() { + this._batches = [] + } + + /** + * Converts a proof into a hexadecimal format. + * @param _leaf - The leaf node to generate the proof for. + * @returns A HexProof containing the proof in hexadecimal format. + */ + getHexProof(_leaf: Buffer): HexProof { + const proof = this.getProof(_leaf) + return proof.map((_batch) => + _batch.map((_node: Node) => { + let position = null + if (_node.position === "left") { + position = "01" + } else if (_node.position === "right") { + position = "02" + } else if (_node.position === null) { + position = "00" + } else { + throw new Error("Invalid Position") + } + return `0x${Buffer.concat([_node.data, Buffer.from(position, "hex")]).toString("hex")}` + }), + ) as `0x${string}`[][] + } + + /** + * Generates a Merkle proof for a specific leaf node. + * @param _leaf - The leaf node to generate the proof for. + * @returns A proof consisting of nodes and their positions in the tree. + */ + getProof(_leaf: Buffer): Proof { + const batchContainingTargetNodeIndex = this._batches.findIndex((_leaves) => + _leaves.find((_l) => Buffer.compare(_l, _leaf) === 0), + ) + + const proof: Proof = [] + for (const [i, leaves] of this._batches.entries()) { + if (batchContainingTargetNodeIndex != i) { + proof.push([{ data: this._calculateBatchRoot(leaves), position: null }]) + } else { + let index = -1 + for (let i = 0; i < leaves.length; i++) { + if (Buffer.compare(_leaf, leaves[i]) === 0) { + index = i + } + } + if (index === -1) throw new Error("Leaf not found") + + const localProof: Node[] = [] + const layers = this._createLayersForBatch(leaves) + for (let i = 0; i < layers.length; i++) { + const layer = layers[i] + const isRightNode = index % 2 + const pairIndex = isRightNode ? index - 1 : index + 1 + if (pairIndex < layer.length) { + localProof.push({ + data: layer[pairIndex], + position: isRightNode ? "left" : "right", + }) + } + index = (index / 2) | 0 + } + proof.push(localProof) + } + } + + return proof + } + + /** + * Adds a batch of leaves to the tree. + * @param _leaves - The array of leaves to add. + */ + pushBatch(_leaves: Buffer[]) { + this._batches.push(_leaves) + } + + /** + * Calculates the root hash of the entire tree. + * @returns The root hash of the tree. + */ + root() { + return this._hashBatchRoots(this._batches.map(this._calculateBatchRoot.bind(this))) + } + + /** + * Verifies the validity of a proof for a given leaf node. + * @param _proof - The proof to verify. + * @param _targetNode - The leaf node being verified. + * @returns True if the proof is valid, otherwise false. + */ + verify(_proof: Proof, _targetNode: Buffer): boolean { + const batchProof = _proof.find((_batch) => _batch.length != 1) // can be 0 or > 1 + if (!batchProof) throw new Error("Invalid Proof") + + let batchRoot = _targetNode + for (let i = 0; i < batchProof.length; i++) { + const node = batchProof[i] + const data = node.data + const isLeftNode = node.position === "left" + const buffers = [] + buffers.push(batchRoot) + buffers[isLeftNode ? "unshift" : "push"](data) + batchRoot = this._hashNodes(buffers[0], buffers[1]) + } + + const batchRoots = _proof.flatMap((_batch, _index) => + _batch.length === 0 ? [_targetNode] : _batch.length === 1 ? _batch.map(({ data }: any) => data) : [batchRoot], + ) + + const calculatedRoot = this._hashBatchRoots(batchRoots) + return Buffer.compare(calculatedRoot, this.root()) === 0 + } + + /** + * Calculates the root hash for a batch of leaves. + * @param _leaves - The leaves of the batch. + * @returns The root hash of the batch. + */ + private _calculateBatchRoot(_leaves: Buffer[]): Buffer { + let currentLayer = _leaves + + while (currentLayer.length > 1) { + let nextLayer: Buffer[] = [] + let i = 0 + while (i < currentLayer.length) { + if (i + 1 < currentLayer.length) { + nextLayer.push(this._hashNodes(currentLayer[i], currentLayer[i + 1])) + i += 2 + } else { + nextLayer.push(currentLayer[i]) + i += 1 + } + } + currentLayer = nextLayer + } + return currentLayer[0] + } + + /** + * Creates all layers of a batch for proof generation. + * @param _nodes - The nodes in the batch. + * @returns A 2D array representing the layers. + */ + private _createLayersForBatch(_nodes: Buffer[]): Buffer[][] { + const layers = [_nodes] + while (_nodes.length > 1) { + const layerIndex = layers.length + layers.push([]) + const layerLimit = _nodes.length + + for (let i = 0; i < _nodes.length; i += 2) { + if (i >= layerLimit) { + layers[layerIndex].push(..._nodes.slice(layerLimit)) + break + } else if (i + 1 === _nodes.length) { + if (_nodes.length % 2 === 1) { + layers[layerIndex].push(_nodes[i]) + continue + } + } + + const left = _nodes[i] + const right = i + 1 === _nodes.length ? left : _nodes[i + 1] + let hash = this._hashNodes(left, right) + layers[layerIndex].push(hash) + } + _nodes = layers[layerIndex] + } + return layers + } + + /** + * Hashes two nodes together. + * @param _node1 - The first node. + * @param _node2 - The second node. + * @returns The hash of the two nodes. + */ + private _hashNodes(_node1: Buffer, _node2: Buffer) { + const hash = crypto.createHash("sha-256") + hash.update(_node1) + hash.update(_node2) + return hash.digest() + } + + /** + * Hashes all batch roots to calculate the tree root. + * @param _batchRoots - The roots of the batches. + * @returns The root of the tree. + */ + private _hashBatchRoots(_batchRoots: Buffer[]) { + let root = _batchRoots.length > 1 ? this._hashNodes(_batchRoots[0], _batchRoots[1]) : _batchRoots[0] + let i = 2 + while (i < _batchRoots.length) { + root = this._hashNodes(root, _batchRoots[i]) + i += 1 + } + return root + } +} + +export default BatchMerkleTree From 1e48b5d5ddd0586ac978633053baef6f0a4f1d0d Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Thu, 19 Dec 2024 19:35:08 +0100 Subject: [PATCH 29/31] feat(solana): puts BashMerkleTree within shared --- packages/solana/Cargo.lock | 10 ++++ .../solana/programs/snapshotter/Cargo.toml | 3 +- .../solana/programs/snapshotter/src/lib.rs | 49 +----------------- .../shared/batch-merkle-tree/Cargo.toml | 18 +++++++ .../shared/batch-merkle-tree/src/lib.rs | 50 +++++++++++++++++++ 5 files changed, 81 insertions(+), 49 deletions(-) create mode 100644 packages/solana/shared/batch-merkle-tree/Cargo.toml create mode 100644 packages/solana/shared/batch-merkle-tree/src/lib.rs diff --git a/packages/solana/Cargo.lock b/packages/solana/Cargo.lock index dba4c42d..2446ae61 100644 --- a/packages/solana/Cargo.lock +++ b/packages/solana/Cargo.lock @@ -623,6 +623,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "batch-merkle-tree" +version = "0.1.0" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "anchor-lang", +] + [[package]] name = "bincode" version = "1.3.3" @@ -2711,6 +2720,7 @@ name = "snapshotter" version = "0.1.0" dependencies = [ "anchor-lang", + "batch-merkle-tree", ] [[package]] diff --git a/packages/solana/programs/snapshotter/Cargo.toml b/packages/solana/programs/snapshotter/Cargo.toml index 0063eadb..d9907549 100644 --- a/packages/solana/programs/snapshotter/Cargo.toml +++ b/packages/solana/programs/snapshotter/Cargo.toml @@ -17,4 +17,5 @@ no-log-ix-name = [] idl-build = ["anchor-lang/idl-build"] [dependencies] -anchor-lang = "0.30.1" \ No newline at end of file +anchor-lang = "0.30.1" +batch-merkle-tree = { path = "../../shared/batch-merkle-tree" } \ No newline at end of file diff --git a/packages/solana/programs/snapshotter/src/lib.rs b/packages/solana/programs/snapshotter/src/lib.rs index 982aea3c..907630f5 100644 --- a/packages/solana/programs/snapshotter/src/lib.rs +++ b/packages/solana/programs/snapshotter/src/lib.rs @@ -30,6 +30,7 @@ pub fn account_hasher( #[program] pub mod snapshotter { use super::*; + use batch_merkle_tree::BatchMerkleTree; // Determines how many accounts are processed per batch during root calculation. pub const BATCH_SIZE: usize = 10; @@ -169,51 +170,3 @@ pub mod snapshotter { Ok(()) } } - -pub struct BatchMerkleTree { - pub root: Hash, -} - -impl From for BatchMerkleTree { - fn from(root: Hash) -> Self { - BatchMerkleTree { root: root } - } -} - -impl BatchMerkleTree { - pub fn new() -> Self { - BatchMerkleTree { - root: Hash::default(), - } - } - - pub fn push_batch(&mut self, leaves: Vec) -> Result<()> { - let mut current_layer = leaves; - - while current_layer.len() > 1 { - let mut next_layer = Vec::new(); - let mut i = 0; - while i < current_layer.len() { - if i + 1 < current_layer.len() { - next_layer.push(hashv(&[ - ¤t_layer[i].to_bytes(), - ¤t_layer[i + 1].to_bytes(), - ])); - i += 2; - } else { - next_layer.push(current_layer[i]); - i += 1; - } - } - current_layer = next_layer; - } - - self.root = if self.root == Hash::default() { - current_layer[0] - } else { - hashv(&[&self.root.to_bytes(), ¤t_layer[0].to_bytes()]) - }; - - Ok(()) - } -} diff --git a/packages/solana/shared/batch-merkle-tree/Cargo.toml b/packages/solana/shared/batch-merkle-tree/Cargo.toml new file mode 100644 index 00000000..8a929223 --- /dev/null +++ b/packages/solana/shared/batch-merkle-tree/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "batch-merkle-tree" +version = "0.1.0" +description = "A merkle tree that allows to calculate a root over a batch of leaves" +edition = "2021" + +[features] +default = [] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build"] + +[dependencies] +alloy-sol-types = "0.7.0" +alloy-primitives = "0.7.0" +anchor-lang = "0.30.1" diff --git a/packages/solana/shared/batch-merkle-tree/src/lib.rs b/packages/solana/shared/batch-merkle-tree/src/lib.rs new file mode 100644 index 00000000..65704f9b --- /dev/null +++ b/packages/solana/shared/batch-merkle-tree/src/lib.rs @@ -0,0 +1,50 @@ +use anchor_lang::prelude::*; +use anchor_lang::solana_program::hash::{hashv, Hash}; + +pub struct BatchMerkleTree { + pub root: Hash, +} + +impl From for BatchMerkleTree { + fn from(root: Hash) -> Self { + BatchMerkleTree { root: root } + } +} + +impl BatchMerkleTree { + pub fn new() -> Self { + BatchMerkleTree { + root: Hash::default(), + } + } + + pub fn push_batch(&mut self, leaves: Vec) -> Result<()> { + let mut current_layer = leaves; + + while current_layer.len() > 1 { + let mut next_layer = Vec::new(); + let mut i = 0; + while i < current_layer.len() { + if i + 1 < current_layer.len() { + next_layer.push(hashv(&[ + ¤t_layer[i].to_bytes(), + ¤t_layer[i + 1].to_bytes(), + ])); + i += 2; + } else { + next_layer.push(current_layer[i]); + i += 1; + } + } + current_layer = next_layer; + } + + self.root = if self.root == Hash::default() { + current_layer[0] + } else { + hashv(&[&self.root.to_bytes(), ¤t_layer[0].to_bytes()]) + }; + + Ok(()) + } +} From d758c618a663f8a8375773985db03824e2255c44 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Thu, 19 Dec 2024 19:37:21 +0100 Subject: [PATCH 30/31] chore(solana): adds missing descriptions --- packages/solana/programs/hashi/Cargo.toml | 2 +- packages/solana/programs/snapshotter/Cargo.toml | 2 +- packages/solana/programs/wormhole-reporter/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/solana/programs/hashi/Cargo.toml b/packages/solana/programs/hashi/Cargo.toml index 8d17924e..6c8d708a 100644 --- a/packages/solana/programs/hashi/Cargo.toml +++ b/packages/solana/programs/hashi/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hashi" version = "0.1.0" -description = "Created with Anchor" +description = "Hashi program" edition = "2021" [lib] diff --git a/packages/solana/programs/snapshotter/Cargo.toml b/packages/solana/programs/snapshotter/Cargo.toml index d9907549..0722c6a2 100644 --- a/packages/solana/programs/snapshotter/Cargo.toml +++ b/packages/solana/programs/snapshotter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snapshotter" version = "0.1.0" -description = "Created with Anchor" +description = "Snapshotter program which is in charge of creating account snapshots" edition = "2021" [lib] diff --git a/packages/solana/programs/wormhole-reporter/Cargo.toml b/packages/solana/programs/wormhole-reporter/Cargo.toml index 50b82dd6..dc556c75 100644 --- a/packages/solana/programs/wormhole-reporter/Cargo.toml +++ b/packages/solana/programs/wormhole-reporter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wormhole-reporter" version = "0.1.0" -description = "Created with Anchor" +description = "Womrhole reporter" edition = "2021" [lib] From fbcb2e8142372fe1d42ac8a2ea3169320df7f59a Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Thu, 19 Dec 2024 19:41:36 +0100 Subject: [PATCH 31/31] chore(solana): updates snapshotter comments --- .../snapshotter/src/contexts/calculate_root.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs b/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs index 73f3b8fe..12627288 100644 --- a/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs +++ b/packages/solana/programs/snapshotter/src/contexts/calculate_root.rs @@ -14,15 +14,6 @@ pub struct CalculateRoot<'info> { /// Specifically, the `calculate_root` function updates fields within the `Config` account, such as the Merkle root, /// finalization status, expected batch number, and nonce. /// - /// ## Example Usage in `calculate_root` Function: - /// - /// ```rust - /// pub fn calculate_root(ctx: Context, batch: u64) -> Result<()> { - /// let config = &mut ctx.accounts.config; - /// // ... perform operations that modify `config` ... - /// } - /// ``` - /// #[account( seeds = [Config::SEED_PREFIX], bump, @@ -38,11 +29,5 @@ pub struct CalculateRoot<'info> { /// - **Read-Only**: The `clock` account is read-only and cannot be modified by the program. It simply provides /// information about the current state of the Solana cluster's timing parameters. /// - /// ## Example Usage in `calculate_root` Function: - /// - /// ```rust - /// let current_epoch = ctx.accounts.clock.epoch; - /// ``` - /// pub clock: Sysvar<'info, Clock>, }