diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ebbe04758b..8bbefe41f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -542,7 +542,7 @@ jobs: if: needs.set-condition.outputs.rebuild_omni_executor == 'true' uses: docker/build-push-action@v6 with: - context: tee-worker/omni-executor/ + context: . file: tee-worker/omni-executor/Dockerfile tags: litentry/omni-executor:latest target: executor-worker diff --git a/common/primitives/core/Cargo.toml b/common/primitives/core/Cargo.toml index 00fd6ad6a8..0947ad12e5 100644 --- a/common/primitives/core/Cargo.toml +++ b/common/primitives/core/Cargo.toml @@ -17,7 +17,7 @@ serde = { version = "1.0", default-features = false, features = ["derive", "allo serde_json = { version = "=1.0.133", default-features = false } strum = { version = "0.26", default-features = false } strum_macros = { version = "0.26", default-features = false } -webpki = { version = "=0.102.0-alpha.3", git = "https://github.com/rustls/webpki", rev = "da923ed", package = "rustls-webpki", default-features = false, features = ["alloc", "ring"] } +webpki = { version = "=0.102.0-alpha.3", git = "https://github.com/rustls/webpki", rev = "da923ed", package = "rustls-webpki", default-features = false, features = ["alloc", "ring"], optional = true } x509-cert = { version = "0.1.0", default-features = false, features = ["alloc"] } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false } @@ -34,13 +34,12 @@ litentry-macros = { path = "macros" } litentry-proc-macros = { path = "proc-macros" } [features] -default = ["std"] +default = ["std", "webpki"] std = [ "chrono/std", "der/std", "hex/std", "ring/std", - "webpki/std", "x509-cert/std", "serde/std", "serde_json/std", @@ -55,7 +54,9 @@ std = [ "sp-consensus-aura/std", "pallet-evm/std", "litentry-hex-utils/std", + "webpki?/std", ] development = [ "litentry-macros/development", ] +webpki = ["dep:webpki"] diff --git a/common/primitives/core/src/teebag/mod.rs b/common/primitives/core/src/teebag/mod.rs index a728adb6e4..b355a1818d 100644 --- a/common/primitives/core/src/teebag/mod.rs +++ b/common/primitives/core/src/teebag/mod.rs @@ -20,7 +20,9 @@ pub use types::*; mod tcb; pub use tcb::*; +#[cfg(feature = "webpki")] mod sgx_verify; +#[cfg(feature = "webpki")] pub use sgx_verify::*; mod quoting_enclave; diff --git a/parachain/pallets/teebag/Cargo.toml b/parachain/pallets/teebag/Cargo.toml index 647fc67a2b..47f4ac88c0 100644 --- a/parachain/pallets/teebag/Cargo.toml +++ b/parachain/pallets/teebag/Cargo.toml @@ -33,7 +33,7 @@ sp-io = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } -core-primitives = { workspace = true } +core-primitives = { workspace = true, features = ["webpki"] } [dev-dependencies] env_logger = { workspace = true } diff --git a/tee-worker/common/litentry/primitives/Cargo.toml b/tee-worker/common/litentry/primitives/Cargo.toml index c47357c7bf..4065fe82cf 100644 --- a/tee-worker/common/litentry/primitives/Cargo.toml +++ b/tee-worker/common/litentry/primitives/Cargo.toml @@ -25,7 +25,7 @@ sgx_tstd = { workspace = true, features = ["net", "thread"], optional = true } itp-sgx-crypto = { workspace = true } itp-sgx-runtime-primitives = { workspace = true } -parentchain-primitives = { workspace = true } +parentchain-primitives = { workspace = true, features = ["webpki"] } [dev-dependencies] base64 = { workspace = true } diff --git a/tee-worker/omni-executor/.gitignore b/tee-worker/omni-executor/.gitignore index 356055fc5e..6b087e3060 100644 --- a/tee-worker/omni-executor/.gitignore +++ b/tee-worker/omni-executor/.gitignore @@ -10,3 +10,5 @@ omni-executor.manifest omni-executor.manifest.sgx omni-executor.sig omni-executor-worker +storage_db +test_storage_db diff --git a/tee-worker/omni-executor/Cargo.lock b/tee-worker/omni-executor/Cargo.lock index 29c7260480..a12626f661 100644 --- a/tee-worker/omni-executor/Cargo.lock +++ b/tee-worker/omni-executor/Cargo.lock @@ -411,7 +411,7 @@ dependencies = [ "serde_json", "tokio", "tokio-stream", - "tower", + "tower 0.5.1", "tracing", "url", ] @@ -576,7 +576,7 @@ dependencies = [ "serde_json", "thiserror 1.0.69", "tokio", - "tower", + "tower 0.5.1", "tracing", "url", ] @@ -591,7 +591,7 @@ dependencies = [ "alloy-transport", "reqwest 0.12.8", "serde_json", - "tower", + "tower 0.5.1", "tracing", "url", ] @@ -666,6 +666,15 @@ version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "aquamarine" version = "0.5.0" @@ -1186,6 +1195,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals 0.3.0", + "bitcoin_hashes 0.14.0", +] + [[package]] name = "base64" version = "0.12.3" @@ -1216,6 +1235,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "binary-merkle-tree" version = "16.0.0" @@ -1282,25 +1307,57 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bitcoin" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026" +dependencies = [ + "base58ck", + "bech32", + "bitcoin-internals 0.3.0", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes 0.14.0", + "hex-conservative 0.2.1", + "hex_lit", + "secp256k1 0.29.1", +] + [[package]] name = "bitcoin-internals" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" + [[package]] name = "bitcoin-io" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals 0.3.0", +] + [[package]] name = "bitcoin_hashes" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" dependencies = [ - "bitcoin-internals", + "bitcoin-internals 0.2.0", "hex-conservative 0.1.2", ] @@ -1631,6 +1688,16 @@ dependencies = [ "thiserror 1.0.69", ] +[[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.1.24" @@ -1933,6 +2000,37 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core-primitives" +version = "0.1.0" +dependencies = [ + "base58", + "base64 0.13.1", + "chrono", + "der 0.6.1", + "frame-support 37.0.1", + "hex", + "hex-literal", + "litentry-hex-utils", + "litentry-macros", + "litentry-proc-macros", + "pallet-evm", + "parity-scale-codec", + "ring 0.16.20", + "rustls-webpki 0.102.0-alpha.3", + "scale-info", + "serde", + "serde_json", + "sp-consensus-aura", + "sp-core 34.0.0", + "sp-io 38.0.0", + "sp-runtime 39.0.3", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "strum", + "strum_macros", + "x509-cert", +] + [[package]] name = "cpufeatures" version = "0.2.14" @@ -2167,6 +2265,17 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "der_derive", + "flagset", +] + [[package]] name = "der" version = "0.7.9" @@ -2174,6 +2283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", + "pem-rfc7468", "zeroize", ] @@ -2191,6 +2301,18 @@ dependencies = [ "rusticata-macros", ] +[[package]] +name = "der_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef71ddb5b3a1f53dee24817c8f70dfa1cb29e804c18d88c228d4bc9c86ee3b9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "deranged" version = "0.3.11" @@ -2406,13 +2528,13 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der", + "der 0.7.9", "digest 0.10.7", "elliptic-curve", "rfc6979", "serdect", "signature 2.2.0", - "spki", + "spki 0.7.3", ] [[package]] @@ -2595,6 +2717,39 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec 0.6.0", + "impl-rlp", + "impl-serde 0.4.0", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e04d24d20b8ff2235cffbf242d5092de3aa45f77c5270ddbfadd2778ca13fea" +dependencies = [ + "bytes", + "ethereum-types", + "hash-db", + "hash256-std-hasher", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "sha3", + "trie-root", +] + [[package]] name = "ethereum-intent-executor" version = "0.1.0" @@ -2606,6 +2761,22 @@ dependencies = [ "tokio", ] +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec 0.6.0", + "impl-rlp", + "impl-serde 0.4.0", + "primitive-types 0.12.2", + "scale-info", + "uint 0.9.5", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -2633,17 +2804,108 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "evm" +version = "0.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767f43e9630cc36cf8ff2777cbb0121b055f0d1fd6eaaa13b46a1808f0d0e7e9" +dependencies = [ + "auto_impl", + "environmental", + "ethereum", + "evm-core", + "evm-gasometer", + "evm-runtime", + "log", + "parity-scale-codec", + "primitive-types 0.12.2", + "rlp", + "scale-info", + "serde", + "sha3", +] + +[[package]] +name = "evm-core" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da6cedc5cedb4208e59467106db0d1f50db01b920920589f8e672c02fdc04f" +dependencies = [ + "parity-scale-codec", + "primitive-types 0.12.2", + "scale-info", + "serde", +] + +[[package]] +name = "evm-gasometer" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dc0eb591abc5cd7b05bef6a036c2bb6c66ab6c5e0c5ce94bfe377ab670b1fd7" +dependencies = [ + "environmental", + "evm-core", + "evm-runtime", + "primitive-types 0.12.2", +] + +[[package]] +name = "evm-runtime" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84bbe09b64ae13a29514048c1bb6fda6374ac0b4f6a1f15a443348ab88ef42cd" +dependencies = [ + "auto_impl", + "environmental", + "evm-core", + "primitive-types 0.12.2", + "sha3", +] + [[package]] name = "executor-core" version = "0.1.0" dependencies = [ "async-trait", + "heima-authentication", "log", "parity-scale-codec", + "primitives", "regex", "tokio", ] +[[package]] +name = "executor-crypto" +version = "0.1.0" +dependencies = [ + "jsonwebtoken", + "log", + "parity-scale-codec", + "rand 0.8.5", + "ring 0.16.20", + "rsa", + "secp256k1 0.29.1", + "serde", + "sp-core 35.0.0", +] + +[[package]] +name = "executor-storage" +version = "0.1.0" +dependencies = [ + "env_logger", + "frame-support 39.0.0", + "log", + "parentchain-api-interface", + "parentchain-rpc-client", + "parity-scale-codec", + "primitives", + "rocksdb", + "sp-state-machine 0.44.0", + "subxt-core", +] + [[package]] name = "executor-worker" version = "0.1.0" @@ -2652,10 +2914,14 @@ dependencies = [ "env_logger", "ethereum-intent-executor", "executor-core", + "executor-storage", "hex", "log", + "native-task-handler", "parentchain-listener", - "parentchain-storage", + "parentchain-rpc-client", + "parentchain-signer", + "rpc-server", "scale-encode 0.10.0", "serde_json", "solana-intent-executor", @@ -2753,6 +3019,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flagset" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" + [[package]] name = "flate2" version = "1.0.35" @@ -2793,6 +3065,64 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fp-account" +version = "1.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=stable2407#2e219e17a526125da003e64ef22ec037917083fa" +dependencies = [ + "hex", + "impl-serde 0.4.0", + "libsecp256k1 0.7.1", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 34.0.0", + "sp-io 38.0.0", + "sp-runtime 39.0.3", + "sp-runtime-interface 28.0.0", + "staging-xcm", +] + +[[package]] +name = "fp-evm" +version = "3.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=stable2407#2e219e17a526125da003e64ef22ec037917083fa" +dependencies = [ + "evm", + "frame-support 37.0.1", + "num_enum", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 34.0.0", + "sp-runtime 39.0.3", +] + +[[package]] +name = "frame-benchmarking" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "frame-support 37.0.1", + "frame-support-procedural 30.0.4", + "frame-system", + "linregress", + "log", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "sp-api 34.0.0", + "sp-application-crypto 38.0.0", + "sp-core 34.0.0", + "sp-io 38.0.0", + "sp-runtime 39.0.3", + "sp-runtime-interface 28.0.0", + "sp-storage 21.0.0", + "static_assertions", +] + [[package]] name = "frame-decode" version = "0.5.0" @@ -2804,7 +3134,19 @@ dependencies = [ "scale-decode", "scale-info", "scale-type-resolver", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-metadata" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", ] [[package]] @@ -2831,6 +3173,47 @@ dependencies = [ "serde", ] +[[package]] +name = "frame-support" +version = "37.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "aquamarine", + "array-bytes", + "bitflags 1.3.2", + "docify", + "environmental", + "frame-metadata 16.0.0", + "frame-support-procedural 30.0.4", + "impl-trait-for-tuples", + "k256", + "log", + "macro_magic", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "serde_json", + "smallvec", + "sp-api 34.0.0", + "sp-arithmetic 26.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-core 34.0.0", + "sp-crypto-hashing-proc-macro 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-genesis-builder 0.15.0", + "sp-inherents 34.0.0", + "sp-io 38.0.0", + "sp-metadata-ir 0.7.0", + "sp-runtime 39.0.3", + "sp-staking 34.0.0", + "sp-state-machine 0.43.0", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-tracing 17.0.0", + "sp-weights 31.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "static_assertions", + "tt-call", +] + [[package]] name = "frame-support" version = "39.0.0" @@ -2844,7 +3227,7 @@ dependencies = [ "docify", "environmental", "frame-metadata 18.0.0", - "frame-support-procedural", + "frame-support-procedural 31.0.0", "impl-trait-for-tuples", "k256", "log", @@ -2855,56 +3238,87 @@ dependencies = [ "serde", "serde_json", "smallvec", - "sp-api", - "sp-arithmetic", - "sp-core", - "sp-crypto-hashing-proc-macro", - "sp-debug-derive", - "sp-genesis-builder", - "sp-inherents", - "sp-io", - "sp-metadata-ir", - "sp-runtime", - "sp-staking", - "sp-state-machine", - "sp-std", - "sp-tracing", - "sp-trie", - "sp-weights", + "sp-api 35.0.0", + "sp-arithmetic 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 35.0.0", + "sp-crypto-hashing-proc-macro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-genesis-builder 0.16.0", + "sp-inherents 35.0.0", + "sp-io 39.0.0", + "sp-metadata-ir 0.8.0", + "sp-runtime 40.0.0", + "sp-staking 37.0.0", + "sp-state-machine 0.44.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-tracing 17.0.1", + "sp-trie 38.0.0", + "sp-weights 31.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions", "tt-call", ] [[package]] name = "frame-support-procedural" -version = "31.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5819d1fcbf6dc177aca405c0b478366527a4763f21457d5ba3a1f4328f656c04" +version = "30.0.4" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" dependencies = [ "Inflector", "cfg-expr", "derive-syn-parse", - "docify", "expander", - "frame-support-procedural-tools", + "frame-support-procedural-tools 13.0.0", "itertools 0.11.0", "macro_magic", "proc-macro-warning", "proc-macro2", "quote", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", "syn 2.0.89", ] [[package]] -name = "frame-support-procedural-tools" -version = "13.0.1" +name = "frame-support-procedural" +version = "31.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a088fd6fda5f53ff0c17fc7551ce8bd0ead14ba742228443c8196296a7369b" +checksum = "5819d1fcbf6dc177aca405c0b478366527a4763f21457d5ba3a1f4328f656c04" dependencies = [ - "frame-support-procedural-tools-derive", - "proc-macro-crate 3.2.0", - "proc-macro2", + "Inflector", + "cfg-expr", + "derive-syn-parse", + "docify", + "expander", + "frame-support-procedural-tools 13.0.1", + "itertools 0.11.0", + "macro_magic", + "proc-macro-warning", + "proc-macro2", + "quote", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 2.0.89", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "13.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "frame-support-procedural-tools-derive 12.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "13.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a088fd6fda5f53ff0c17fc7551ce8bd0ead14ba742228443c8196296a7369b" +dependencies = [ + "frame-support-procedural-tools-derive 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 3.2.0", + "proc-macro2", "quote", "syn 2.0.89", ] @@ -2920,6 +3334,36 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "frame-support-procedural-tools-derive" +version = "12.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "frame-system" +version = "37.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "cfg-if", + "docify", + "frame-support 37.0.1", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 34.0.0", + "sp-io 38.0.0", + "sp-runtime 39.0.3", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-version 37.0.0", + "sp-weights 31.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", +] + [[package]] name = "fs-err" version = "2.11.0" @@ -3170,6 +3614,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hash-db" version = "0.16.0" @@ -3226,6 +3689,27 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "heima-authentication" +version = "0.1.0" +dependencies = [ + "executor-crypto", + "log", + "parity-scale-codec", + "primitives", + "serde", +] + +[[package]] +name = "heima-identity-verification" +version = "0.1.0" +dependencies = [ + "async-trait", + "log", + "rand 0.8.5", + "sendgrid", +] + [[package]] name = "hermit-abi" version = "0.3.9" @@ -3268,6 +3752,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + [[package]] name = "histogram" version = "0.6.9" @@ -3388,7 +3878,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -3411,9 +3901,11 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2 0.4.7", "http 1.1.0", "http-body 1.0.1", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -3538,6 +4030,24 @@ dependencies = [ "uint 0.10.0", ] +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + [[package]] name = "impl-serde" version = "0.5.0" @@ -3740,8 +4250,10 @@ checksum = "c5c71d8c1a731cc4227c2f698d377e7848ca12c8a48866fc5e6951c43a4db843" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", + "jsonrpsee-server", "jsonrpsee-types", "jsonrpsee-ws-client", + "tokio", ] [[package]] @@ -3756,7 +4268,7 @@ dependencies = [ "jsonrpsee-core", "pin-project", "rustls 0.23.19", - "rustls-pki-types", + "rustls-pki-types 1.10.0", "rustls-platform-verifier 0.3.4", "soketto", "thiserror 1.0.69", @@ -3774,10 +4286,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2882f6f8acb9fdaec7cefc4fd607119a9bd709831df7d7672a1d3b644628280" dependencies = [ "async-trait", + "bytes", "futures-timer", "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "jsonrpsee-types", + "parking_lot", "pin-project", + "rand 0.8.5", "rustc-hash 2.0.0", "serde", "serde_json", @@ -3787,6 +4305,33 @@ dependencies = [ "tracing", ] +[[package]] +name = "jsonrpsee-server" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82ad8ddc14be1d4290cd68046e7d1d37acd408efed6d3ca08aefcc3ad6da069c" +dependencies = [ + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-util", + "jsonrpsee-core", + "jsonrpsee-types", + "pin-project", + "route-recognizer", + "serde", + "serde_json", + "soketto", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tokio-util", + "tower 0.4.13", + "tracing", +] + [[package]] name = "jsonrpsee-types" version = "0.24.7" @@ -3812,6 +4357,21 @@ dependencies = [ "url", ] +[[package]] +name = "jsonwebtoken" +version = "9.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" +dependencies = [ + "base64 0.21.7", + "js-sys", + "pem 3.0.4", + "ring 0.17.8", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "k256" version = "0.13.4" @@ -3860,6 +4420,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin 0.9.8", +] [[package]] name = "lazycell" @@ -3869,9 +4432,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" @@ -4011,12 +4574,42 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linregress" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9eda9dcf4f2a99787827661f312ac3219292549c2ee992bf9a6248ffb066bf7" +dependencies = [ + "nalgebra", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litentry-hex-utils" +version = "0.1.0" +dependencies = [ + "hex", +] + +[[package]] +name = "litentry-macros" +version = "0.1.0" + +[[package]] +name = "litentry-proc-macros" +version = "0.1.0" +dependencies = [ + "cargo_toml", + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "lock_api" version = "0.4.12" @@ -4109,6 +4702,16 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matrixmultiply" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +dependencies = [ + "autocfg", + "rawpointer", +] + [[package]] name = "memchr" version = "2.7.4" @@ -4202,6 +4805,38 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" +[[package]] +name = "nalgebra" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" +dependencies = [ + "approx", + "matrixmultiply", + "num-complex 0.4.6", + "num-rational 0.4.2", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "native-task-handler" +version = "0.1.0" +dependencies = [ + "executor-core", + "executor-crypto", + "executor-storage", + "heima-authentication", + "log", + "parentchain-api-interface", + "parentchain-rpc-client", + "parentchain-signer", + "parity-scale-codec", + "primitives", + "tokio", +] + [[package]] name = "native-tls" version = "0.2.12" @@ -4283,7 +4918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" dependencies = [ "num-bigint 0.2.6", - "num-complex", + "num-complex 0.2.4", "num-integer", "num-iter", "num-rational 0.2.4", @@ -4311,6 +4946,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-complex" version = "0.2.4" @@ -4321,6 +4973,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -4531,6 +5192,29 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "pallet-evm" +version = "6.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=stable2407#2e219e17a526125da003e64ef22ec037917083fa" +dependencies = [ + "environmental", + "evm", + "fp-account", + "fp-evm", + "frame-benchmarking", + "frame-support 37.0.1", + "frame-system", + "hash-db", + "hex-literal", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "sp-core 34.0.0", + "sp-io 38.0.0", + "sp-runtime 39.0.3", +] + [[package]] name = "parentchain-api-interface" version = "0.1.0" @@ -4545,28 +5229,22 @@ dependencies = [ "async-trait", "env_logger", "executor-core", + "executor-storage", "hex", "log", "parentchain-api-interface", - "parentchain-primitives", "parentchain-rpc-client", - "parentchain-storage", + "parentchain-signer", "parity-scale-codec", + "primitives", "scale-encode 0.10.0", - "sp-core", + "sp-core 35.0.0", "subxt", "subxt-core", "subxt-signer", "tokio", ] -[[package]] -name = "parentchain-primitives" -version = "0.1.0" -dependencies = [ - "executor-core", -] - [[package]] name = "parentchain-rpc-client" version = "0.1.0" @@ -4574,27 +5252,26 @@ dependencies = [ "async-trait", "env_logger", "log", - "parentchain-primitives", "parity-scale-codec", + "primitives", "scale-encode 0.10.0", "subxt", "subxt-core", + "tokio", ] [[package]] -name = "parentchain-storage" +name = "parentchain-signer" version = "0.1.0" dependencies = [ "env_logger", "executor-core", - "frame-support", + "executor-crypto", "log", - "parentchain-api-interface", "parentchain-rpc-client", "parity-scale-codec", - "rocksdb", - "sp-state-machine", "subxt-core", + "subxt-signer", ] [[package]] @@ -4718,6 +5395,25 @@ dependencies = [ "base64 0.13.1", ] +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -4787,14 +5483,25 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der 0.7.9", + "pkcs8", + "spki 0.7.3", +] + [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", - "spki", + "der 0.7.9", + "spki 0.7.3", ] [[package]] @@ -4809,7 +5516,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb819108697967452fa6d8d96ab4c0d48cbaa423b3156499dcb24f1cf95d6775" dependencies = [ - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4926,6 +5633,9 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec 0.6.0", + "impl-rlp", + "impl-serde 0.4.0", + "scale-info", "uint 0.9.5", ] @@ -4938,11 +5648,27 @@ dependencies = [ "fixed-hash", "impl-codec 0.7.0", "impl-num-traits", - "impl-serde", + "impl-serde 0.5.0", "scale-info", "uint 0.10.0", ] +[[package]] +name = "primitives" +version = "0.1.0" +dependencies = [ + "base64 0.22.1", + "bitcoin", + "core-primitives", + "executor-crypto", + "hex", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 35.0.0", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -5104,10 +5830,10 @@ dependencies = [ "bytes", "getrandom 0.2.15", "rand 0.8.5", - "ring", + "ring 0.17.8", "rustc-hash 2.0.0", "rustls 0.23.19", - "rustls-pki-types", + "rustls-pki-types 1.10.0", "rustls-platform-verifier 0.4.0", "slab", "thiserror 2.0.6", @@ -5235,6 +5961,12 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rayon" version = "1.10.0" @@ -5340,7 +6072,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", @@ -5436,6 +6168,21 @@ dependencies = [ "subtle", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + [[package]] name = "ring" version = "0.17.8" @@ -5446,29 +6193,90 @@ dependencies = [ "cfg-if", "getrandom 0.2.15", "libc", - "spin", - "untrusted", + "spin 0.9.8", + "untrusted 0.9.0", "windows-sys 0.52.0", ] [[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rlp-derive", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rocksdb" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26ec73b20525cb235bad420f911473b69f9fe27cc856c5461bccd7e4af037f43" +dependencies = [ + "libc", + "librocksdb-sys", +] + +[[package]] +name = "route-recognizer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" + +[[package]] +name = "rpc-server" +version = "0.1.0" dependencies = [ - "bytes", - "rustc-hex", + "executor-core", + "executor-crypto", + "executor-storage", + "heima-authentication", + "heima-identity-verification", + "hex", + "jsonrpsee", + "log", + "native-task-handler", + "parentchain-rpc-client", + "parity-scale-codec", + "primitives", + "rand 0.8.5", + "serde", + "serde_json", + "tokio", ] [[package]] -name = "rocksdb" -version = "0.23.0" +name = "rsa" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ec73b20525cb235bad420f911473b69f9fe27cc856c5461bccd7e4af037f43" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ - "libc", - "librocksdb-sys", + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "sha2 0.10.8", + "signature 2.2.0", + "spki 0.7.3", + "subtle", + "zeroize", ] [[package]] @@ -5572,7 +6380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring", + "ring 0.17.8", "rustls-webpki 0.101.7", "sct", ] @@ -5585,8 +6393,8 @@ checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "log", "once_cell", - "ring", - "rustls-pki-types", + "ring 0.17.8", + "rustls-pki-types 1.10.0", "rustls-webpki 0.102.8", "subtle", "zeroize", @@ -5600,7 +6408,7 @@ checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", "rustls-pemfile 2.2.0", - "rustls-pki-types", + "rustls-pki-types 1.10.0", "schannel", "security-framework", ] @@ -5620,9 +6428,15 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "rustls-pki-types", + "rustls-pki-types 1.10.0", ] +[[package]] +name = "rustls-pki-types" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d3edd6cdcdf26eda538757038343986e666d0b8ba4b5ac1de663b78475550d" + [[package]] name = "rustls-pki-types" version = "1.10.0" @@ -5686,8 +6500,18 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.0-alpha.3" +source = "git+https://github.com/rustls/webpki?rev=da923ed#da923edaab56f599971e58773617fb574cd019dc" +dependencies = [ + "ring 0.16.20", + "rustls-pki-types 0.2.3", + "untrusted 0.9.0", ] [[package]] @@ -5696,9 +6520,9 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", + "ring 0.17.8", + "rustls-pki-types 1.10.0", + "untrusted 0.9.0", ] [[package]] @@ -5735,6 +6559,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + [[package]] name = "salsa20" version = "0.10.2" @@ -5996,8 +6829,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -6007,7 +6840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", - "der", + "der 0.7.9", "generic-array", "pkcs8", "serdect", @@ -6024,6 +6857,16 @@ dependencies = [ "secp256k1-sys 0.9.2", ] +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "bitcoin_hashes 0.14.0", + "secp256k1-sys 0.10.1", +] + [[package]] name = "secp256k1" version = "0.30.0" @@ -6119,11 +6962,25 @@ dependencies = [ "pest", ] +[[package]] +name = "sendgrid" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c3c66709377c4d2bcbf46c298c5e07db62398793d20a69ca99b4ec6f9bfe5fd" +dependencies = [ + "data-encoding", + "reqwest 0.12.8", + "serde", + "serde_json", + "thiserror 1.0.69", + "url", +] + [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] @@ -6139,9 +6996,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -6309,12 +7166,37 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simba" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" +dependencies = [ + "approx", + "num-complex 0.4.6", + "num-traits", + "paste", + "wide", +] + [[package]] name = "simple-mermaid" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "620a1d43d70e142b1d46a929af51d44f383db9c7a2ec122de2cd992ccfcf3c18" +[[package]] +name = "simple_asn1" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "thiserror 2.0.6", + "time", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -6468,6 +7350,7 @@ dependencies = [ "base64 0.22.1", "bytes", "futures", + "http 1.1.0", "httparse", "log", "rand 0.8.5", @@ -7502,7 +8385,7 @@ dependencies = [ "libc", "log", "nix", - "pem", + "pem 1.1.1", "percentage", "quinn", "quinn-proto", @@ -7748,6 +8631,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "sp-api" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "docify", + "hash-db", + "log", + "parity-scale-codec", + "scale-info", + "sp-api-proc-macro 20.0.0", + "sp-core 34.0.0", + "sp-externalities 0.29.0", + "sp-metadata-ir 0.7.0", + "sp-runtime 39.0.3", + "sp-runtime-interface 28.0.0", + "sp-state-machine 0.43.0", + "sp-trie 37.0.0", + "sp-version 37.0.0", + "thiserror 1.0.69", +] + [[package]] name = "sp-api" version = "35.0.0" @@ -7759,18 +8664,32 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-api-proc-macro", - "sp-core", - "sp-externalities", - "sp-metadata-ir", - "sp-runtime", - "sp-runtime-interface", - "sp-state-machine", - "sp-trie", - "sp-version", + "sp-api-proc-macro 21.0.0", + "sp-core 35.0.0", + "sp-externalities 0.30.0", + "sp-metadata-ir 0.8.0", + "sp-runtime 40.0.0", + "sp-runtime-interface 29.0.0", + "sp-state-machine 0.44.0", + "sp-trie 38.0.0", + "sp-version 38.0.0", "thiserror 1.0.69", ] +[[package]] +name = "sp-api-proc-macro" +version = "20.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "Inflector", + "blake2", + "expander", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "sp-api-proc-macro" version = "21.0.0" @@ -7786,6 +8705,18 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "sp-application-crypto" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 34.0.0", + "sp-io 38.0.0", +] + [[package]] name = "sp-application-crypto" version = "39.0.0" @@ -7795,8 +8726,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", + "sp-core 35.0.0", + "sp-io 39.0.0", ] [[package]] @@ -7811,10 +8742,97 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions", +] + +[[package]] +name = "sp-arithmetic" +version = "26.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "docify", + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", "static_assertions", ] +[[package]] +name = "sp-consensus-aura" +version = "0.40.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "sp-api 34.0.0", + "sp-application-crypto 38.0.0", + "sp-consensus-slots", + "sp-inherents 34.0.0", + "sp-runtime 39.0.3", + "sp-timestamp", +] + +[[package]] +name = "sp-consensus-slots" +version = "0.40.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-timestamp", +] + +[[package]] +name = "sp-core" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "array-bytes", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde 0.4.0", + "itertools 0.11.0", + "k256", + "libsecp256k1 0.7.1", + "log", + "merlin", + "parity-bip39", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types 0.12.2", + "rand 0.8.5", + "scale-info", + "schnorrkel", + "secp256k1 0.28.2", + "secrecy 0.8.0", + "serde", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-externalities 0.29.0", + "sp-runtime-interface 28.0.0", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-storage 21.0.0", + "ss58-registry", + "substrate-bip39 0.6.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "thiserror 1.0.69", + "tracing", + "w3f-bls", + "zeroize", +] + [[package]] name = "sp-core" version = "35.0.0" @@ -7831,7 +8849,7 @@ dependencies = [ "futures", "hash-db", "hash256-std-hasher", - "impl-serde", + "impl-serde 0.5.0", "itertools 0.11.0", "k256", "libsecp256k1 0.7.1", @@ -7848,14 +8866,14 @@ dependencies = [ "secp256k1 0.28.2", "secrecy 0.8.0", "serde", - "sp-crypto-hashing", - "sp-debug-derive", - "sp-externalities", - "sp-runtime-interface", - "sp-std", - "sp-storage", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-externalities 0.30.0", + "sp-runtime-interface 29.0.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-storage 22.0.0", "ss58-registry", - "substrate-bip39", + "substrate-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 1.0.69", "tracing", "w3f-bls", @@ -7876,6 +8894,19 @@ dependencies = [ "twox-hash", ] +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.1.0" @@ -7883,7 +8914,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 2.0.89", +] + +[[package]] +name = "sp-crypto-hashing-proc-macro" +version = "0.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "quote", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", "syn 2.0.89", ] @@ -7898,6 +8939,26 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "sp-externalities" +version = "0.29.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-storage 21.0.0", +] + [[package]] name = "sp-externalities" version = "0.30.0" @@ -7906,7 +8967,19 @@ checksum = "30cbf059dce180a8bf8b6c8b08b6290fa3d1c7f069a60f1df038ab5dd5fc0ba6" dependencies = [ "environmental", "parity-scale-codec", - "sp-storage", + "sp-storage 22.0.0", +] + +[[package]] +name = "sp-genesis-builder" +version = "0.15.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde_json", + "sp-api 34.0.0", + "sp-runtime 39.0.3", ] [[package]] @@ -7918,8 +8991,21 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde_json", - "sp-api", - "sp-runtime", + "sp-api 35.0.0", + "sp-runtime 40.0.0", +] + +[[package]] +name = "sp-inherents" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "async-trait", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime 39.0.3", + "thiserror 1.0.69", ] [[package]] @@ -7932,10 +9018,36 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 40.0.0", "thiserror 1.0.69", ] +[[package]] +name = "sp-io" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "bytes", + "docify", + "ed25519-dalek 2.1.1", + "libsecp256k1 0.7.1", + "log", + "parity-scale-codec", + "polkavm-derive", + "rustversion", + "secp256k1 0.28.2", + "sp-core 34.0.0", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-externalities 0.29.0", + "sp-keystore 0.40.0", + "sp-runtime-interface 28.0.0", + "sp-state-machine 0.43.0", + "sp-tracing 17.0.0", + "sp-trie 37.0.0", + "tracing", + "tracing-core", +] + [[package]] name = "sp-io" version = "39.0.0" @@ -7951,18 +9063,29 @@ dependencies = [ "polkavm-derive", "rustversion", "secp256k1 0.28.2", - "sp-core", - "sp-crypto-hashing", - "sp-externalities", - "sp-keystore", - "sp-runtime-interface", - "sp-state-machine", - "sp-tracing", - "sp-trie", + "sp-core 35.0.0", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-externalities 0.30.0", + "sp-keystore 0.41.0", + "sp-runtime-interface 29.0.0", + "sp-state-machine 0.44.0", + "sp-tracing 17.0.1", + "sp-trie 38.0.0", "tracing", "tracing-core", ] +[[package]] +name = "sp-keystore" +version = "0.40.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core 34.0.0", + "sp-externalities 0.29.0", +] + [[package]] name = "sp-keystore" version = "0.41.0" @@ -7971,8 +9094,18 @@ checksum = "c1d41475fcdf253f9f0da839564c1b7f8a95c6a293ddfffd6e48e3671e76f33b" dependencies = [ "parity-scale-codec", "parking_lot", - "sp-core", - "sp-externalities", + "sp-core 35.0.0", + "sp-externalities 0.30.0", +] + +[[package]] +name = "sp-metadata-ir" +version = "0.7.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "frame-metadata 16.0.0", + "parity-scale-codec", + "scale-info", ] [[package]] @@ -7986,6 +9119,16 @@ dependencies = [ "scale-info", ] +[[package]] +name = "sp-panic-handler" +version = "13.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + [[package]] name = "sp-panic-handler" version = "13.0.1" @@ -7996,6 +9139,32 @@ dependencies = [ "regex", ] +[[package]] +name = "sp-runtime" +version = "39.0.3" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "docify", + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "num-traits", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde", + "simple-mermaid", + "sp-application-crypto 38.0.0", + "sp-arithmetic 26.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-core 34.0.0", + "sp-io 38.0.0", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-weights 31.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "tracing", +] + [[package]] name = "sp-runtime" version = "40.0.0" @@ -8015,17 +9184,36 @@ dependencies = [ "scale-info", "serde", "simple-mermaid", - "sp-application-crypto", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-std", - "sp-trie", - "sp-weights", + "sp-application-crypto 39.0.0", + "sp-arithmetic 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 35.0.0", + "sp-io 39.0.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-trie 38.0.0", + "sp-weights 31.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", "tuplex", ] +[[package]] +name = "sp-runtime-interface" +version = "28.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive", + "primitive-types 0.12.2", + "sp-externalities 0.29.0", + "sp-runtime-interface-proc-macro 18.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-storage 21.0.0", + "sp-tracing 17.0.0", + "sp-wasm-interface 21.0.0", + "static_assertions", +] + [[package]] name = "sp-runtime-interface" version = "29.0.0" @@ -8037,12 +9225,12 @@ dependencies = [ "parity-scale-codec", "polkavm-derive", "primitive-types 0.13.1", - "sp-externalities", - "sp-runtime-interface-proc-macro", - "sp-std", - "sp-storage", - "sp-tracing", - "sp-wasm-interface", + "sp-externalities 0.30.0", + "sp-runtime-interface-proc-macro 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-storage 22.0.0", + "sp-tracing 17.0.1", + "sp-wasm-interface 21.0.1", "static_assertions", ] @@ -8060,6 +9248,32 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "18.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "sp-staking" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 34.0.0", + "sp-runtime 39.0.3", +] + [[package]] name = "sp-staking" version = "37.0.0" @@ -8070,8 +9284,28 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-runtime", + "sp-core 35.0.0", + "sp-runtime 40.0.0", +] + +[[package]] +name = "sp-state-machine" +version = "0.43.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand 0.8.5", + "smallvec", + "sp-core 34.0.0", + "sp-externalities 0.29.0", + "sp-panic-handler 13.0.0", + "sp-trie 37.0.0", + "thiserror 1.0.69", + "tracing", + "trie-db", ] [[package]] @@ -8086,10 +9320,10 @@ dependencies = [ "parking_lot", "rand 0.8.5", "smallvec", - "sp-core", - "sp-externalities", - "sp-panic-handler", - "sp-trie", + "sp-core 35.0.0", + "sp-externalities 0.30.0", + "sp-panic-handler 13.0.1", + "sp-trie 38.0.0", "thiserror 1.0.69", "tracing", "trie-db", @@ -8101,17 +9335,57 @@ version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" +[[package]] +name = "sp-std" +version = "14.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" + +[[package]] +name = "sp-storage" +version = "21.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "impl-serde 0.4.0", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", +] + [[package]] name = "sp-storage" version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee3b70ca340e41cde9d2e069d354508a6e37a6573d66f7cc38f11549002f64ec" dependencies = [ - "impl-serde", + "impl-serde 0.5.0", "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive", + "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-timestamp" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "async-trait", + "parity-scale-codec", + "sp-inherents 34.0.0", + "sp-runtime 39.0.3", + "thiserror 1.0.69", +] + +[[package]] +name = "sp-tracing" +version = "17.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "parity-scale-codec", + "tracing", + "tracing-core", + "tracing-subscriber", ] [[package]] @@ -8126,6 +9400,29 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "sp-trie" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "ahash", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "rand 0.8.5", + "scale-info", + "schnellru", + "sp-core 34.0.0", + "sp-externalities 0.29.0", + "thiserror 1.0.69", + "tracing", + "trie-db", + "trie-root", +] + [[package]] name = "sp-trie" version = "38.0.0" @@ -8141,32 +9438,60 @@ dependencies = [ "rand 0.8.5", "scale-info", "schnellru", - "sp-core", - "sp-externalities", + "sp-core 35.0.0", + "sp-externalities 0.30.0", "thiserror 1.0.69", "tracing", "trie-db", "trie-root", ] +[[package]] +name = "sp-version" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "impl-serde 0.4.0", + "parity-scale-codec", + "parity-wasm", + "scale-info", + "serde", + "sp-crypto-hashing-proc-macro 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-runtime 39.0.3", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-version-proc-macro 14.0.0", + "thiserror 1.0.69", +] + [[package]] name = "sp-version" version = "38.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7561e88742bc47b2f5fbdcab77a1cd98cf04117a3e163c1aadd58b9a592a18" dependencies = [ - "impl-serde", + "impl-serde 0.5.0", "parity-scale-codec", "parity-wasm", "scale-info", "serde", - "sp-crypto-hashing-proc-macro", - "sp-runtime", - "sp-std", - "sp-version-proc-macro", + "sp-crypto-hashing-proc-macro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 40.0.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-version-proc-macro 15.0.0", "thiserror 1.0.69", ] +[[package]] +name = "sp-version-proc-macro" +version = "14.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "sp-version-proc-macro" version = "15.0.0" @@ -8180,6 +9505,16 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "sp-wasm-interface" +version = "21.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "impl-trait-for-tuples", + "log", + "parity-scale-codec", +] + [[package]] name = "sp-wasm-interface" version = "21.0.1" @@ -8203,10 +9538,30 @@ dependencies = [ "scale-info", "serde", "smallvec", - "sp-arithmetic", - "sp-debug-derive", + "sp-arithmetic 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-weights" +version = "31.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic 26.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" @@ -8222,6 +9577,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + [[package]] name = "spki" version = "0.7.3" @@ -8229,7 +9594,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.9", ] [[package]] @@ -8439,6 +9804,24 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "staging-xcm" +version = "14.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "array-bytes", + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-weights 31.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=stable2407)", + "xcm-procedural", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -8496,6 +9879,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "substrate-bip39" +version = "0.6.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "hmac 0.12.1", + "pbkdf2 0.12.2", + "schnorrkel", + "sha2 0.10.8", + "zeroize", +] + [[package]] name = "subtle" version = "2.6.1" @@ -8514,7 +9909,7 @@ dependencies = [ "frame-metadata 17.0.0", "futures", "hex", - "impl-serde", + "impl-serde 0.5.0", "jsonrpsee", "parity-scale-codec", "polkadot-sdk", @@ -8569,7 +9964,7 @@ dependencies = [ "frame-metadata 17.0.0", "hashbrown 0.14.5", "hex", - "impl-serde", + "impl-serde 0.5.0", "keccak-hash", "parity-scale-codec", "polkadot-sdk", @@ -8905,9 +10300,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -8923,9 +10318,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", @@ -8959,7 +10354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ "rustls 0.23.19", - "rustls-pki-types", + "rustls-pki-types 1.10.0", "tokio", ] @@ -9047,6 +10442,21 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.5.1" @@ -9314,6 +10724,12 @@ dependencies = [ "void", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -9519,7 +10935,7 @@ dependencies = [ "num-derive", "num-traits", "smallvec", - "spin", + "spin 0.9.8", "wasmi_collections", "wasmi_core", "wasmparser-nostd", @@ -9583,7 +10999,7 @@ version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cd5da49bdf1f30054cfe0b8ce2958b8fbeb67c4d82c8967a598af481bef255c" dependencies = [ - "rustls-pki-types", + "rustls-pki-types 1.10.0", ] [[package]] @@ -9607,7 +11023,17 @@ version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ - "rustls-pki-types", + "rustls-pki-types 1.10.0", +] + +[[package]] +name = "wide" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" +dependencies = [ + "bytemuck", + "safe_arch", ] [[package]] @@ -9868,6 +11294,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x509-cert" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d224a125dec5adda27d0346b9cae9794830279c4f9c27e4ab0b6c408d54012" +dependencies = [ + "const-oid", + "der 0.6.1", + "flagset", + "spki 0.6.0", +] + [[package]] name = "x509-parser" version = "0.14.0" @@ -9886,6 +11324,17 @@ dependencies = [ "time", ] +[[package]] +name = "xcm-procedural" +version = "10.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=stable2407#6ae6bbcd5086c994efc05127adb2b142caa9cbd6" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "yap" version = "0.11.0" diff --git a/tee-worker/omni-executor/Cargo.toml b/tee-worker/omni-executor/Cargo.toml index 146e195bd4..ab4c7a1ed8 100644 --- a/tee-worker/omni-executor/Cargo.toml +++ b/tee-worker/omni-executor/Cargo.toml @@ -1,13 +1,20 @@ [workspace] members = [ + "executor-crypto", "executor-core", "executor-worker", + "ethereum/intent-executor", + "ethereum/intent-executor", + "heima/authentication", + "heima/identity-verification", + "native-task-handler", "parentchain/listener", "parentchain/api-interface", "parentchain/rpc-client", - "parentchain/storage", - "parentchain/primitives", - "ethereum/intent-executor", + "parentchain/signer", + "primitives", + "rpc-server", + "executor-storage", "solana/intent-executor", ] @@ -19,14 +26,25 @@ edition = "2021" [workspace.dependencies] alloy = "0.3.6" async-trait = "0.1.82" +base64 = "0.22.1" +bitcoin = "0.32.5" clap = "4.5.17" env_logger = "0.11.5" frame-support = { version = "39.0.0", features = ["std"] } -hex = "0.4.3" +hex = "0.4" +jsonrpsee = { version = "0.24", features = ["server"] } +jsonwebtoken = "9.3.0" log = "0.4.22" parity-scale-codec = "3.6.12" +rand = "0.8.5" regex = "1.7" +ring = "0.16.20" +rsa = "0.9.7" scale-encode = "0.10.0" +scale-info = "2.11.6" +secp256k1 = "=0.29.1" +serde = { version = "1.0.217", features = ["derive"] } +serde_json = "1.0" solana-client = "2.1.5" solana-sdk = "2.1.5" sp-core = "35.0.0" @@ -34,15 +52,23 @@ sp-state-machine = { version = "0.44.0", features = ["std"] } subxt = "0.38.0" subxt-core = "0.38.0" subxt-signer = { version = "0.38.0", features = ["subxt"] } -tokio = "1.40.0" +tokio = "1.43.0" +# Local dependencies ethereum-intent-executor = { path = "ethereum/intent-executor" } executor-core = { path = "executor-core" } +executor-crypto = { path = "executor-crypto" } +executor-storage = { path = "executor-storage" } +heima-authentication = { path = "heima/authentication" } +heima-identity-verification = { path = "heima/identity-verification" } +heima-primitives = { package = "core-primitives", path = "../../common/primitives/core", default-features = false, features = ["std"] } +native-task-handler = { path = "native-task-handler" } parentchain-api-interface = { path = "parentchain/api-interface" } parentchain-listener = { path = "parentchain/listener" } -parentchain-primitives = { path = "parentchain/primitives" } parentchain-rpc-client = { path = "parentchain/rpc-client" } -parentchain-storage = { path = "parentchain/storage" } +parentchain-signer = { path = "parentchain/signer" } +primitives = { path = "primitives" } +rpc-server = { path = "rpc-server" } solana-intent-executor = { path = "solana/intent-executor" } [workspace.lints.clippy] diff --git a/tee-worker/omni-executor/Dockerfile b/tee-worker/omni-executor/Dockerfile index ba42147f1e..c805bb6b2c 100644 --- a/tee-worker/omni-executor/Dockerfile +++ b/tee-worker/omni-executor/Dockerfile @@ -7,9 +7,10 @@ FROM rust:1.82-bookworm AS plain-builder RUN apt-get update && apt-get install -y clang -ENV SRC_DIR=/home/ubuntu/omni-executor -COPY . $SRC_DIR +ENV SRC_DIR=/home/ubuntu/tee-worker/omni-executor +COPY tee-worker/omni-executor $SRC_DIR +COPY common /home/ubuntu/common WORKDIR $SRC_DIR RUN cargo build --release @@ -19,7 +20,7 @@ RUN cargo build --release ################################################## FROM node:20-bookworm-slim AS executor-worker -ENV SRC_DIR=/home/ubuntu/omni-executor +ENV SRC_DIR=/home/ubuntu/tee-worker/omni-executor ENV BIN_DIR=/usr/local/bin WORKDIR $BIN_DIR @@ -86,4 +87,4 @@ CMD ["$BIN_DIR/executor-worker"] # RUN chmod +x $EXECUT_DIR/omni-executor-worker # RUN ls -al $EXECUT_DIR # RUN ldd $EXECUT_DIR/omni-executor-worker && $EXECUT_DIR/omni-executor-worker --version -# CMD ["$EXECUT_DIR/omni-executor-worker"] \ No newline at end of file +# CMD ["$EXECUT_DIR/omni-executor-worker"] diff --git a/tee-worker/omni-executor/Makefile b/tee-worker/omni-executor/Makefile index c0fc34324c..b72f93b58e 100644 --- a/tee-worker/omni-executor/Makefile +++ b/tee-worker/omni-executor/Makefile @@ -68,7 +68,7 @@ distclean: clean .PHONY: build-docker build-docker: - docker build --target executor-worker -t litentry/omni-executor:latest -f $(OMNI_DIR)/Dockerfile $(OMNI_DIR) + docker build --target executor-worker -t litentry/omni-executor:latest -f $(OMNI_DIR)/Dockerfile $(ROOTDIR) .PHONY: start-local start-local: diff --git a/tee-worker/omni-executor/executor-core/Cargo.toml b/tee-worker/omni-executor/executor-core/Cargo.toml index 9e182bef2c..a729161406 100644 --- a/tee-worker/omni-executor/executor-core/Cargo.toml +++ b/tee-worker/omni-executor/executor-core/Cargo.toml @@ -11,5 +11,9 @@ parity-scale-codec = { workspace = true, features = ["derive"] } regex = { workspace = true } tokio = { workspace = true } +# Local dependencies +heima-authentication = { workspace = true } +primitives = { workspace = true } + [lints] workspace = true diff --git a/tee-worker/omni-executor/executor-core/src/fetcher.rs b/tee-worker/omni-executor/executor-core/src/fetcher.rs index 3efafbe779..6f18108778 100644 --- a/tee-worker/omni-executor/executor-core/src/fetcher.rs +++ b/tee-worker/omni-executor/executor-core/src/fetcher.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::primitives::GetEventId; use async_trait::async_trait; +use primitives::GetEventId; /// Returns the last finalized block number #[async_trait] diff --git a/tee-worker/omni-executor/executor-core/src/lib.rs b/tee-worker/omni-executor/executor-core/src/lib.rs index 7f7d9a48b2..bda68a965d 100644 --- a/tee-worker/omni-executor/executor-core/src/lib.rs +++ b/tee-worker/omni-executor/executor-core/src/lib.rs @@ -19,6 +19,6 @@ pub mod fetcher; pub mod intent_executor; pub mod key_store; pub mod listener; +pub mod native_call; pub mod primitives; -pub mod storage; pub mod sync_checkpoint_repository; diff --git a/tee-worker/omni-executor/executor-core/src/listener.rs b/tee-worker/omni-executor/executor-core/src/listener.rs index b439b22ed2..a547c3db82 100644 --- a/tee-worker/omni-executor/executor-core/src/listener.rs +++ b/tee-worker/omni-executor/executor-core/src/listener.rs @@ -21,8 +21,8 @@ use tokio::{runtime::Handle, sync::oneshot::Receiver}; use crate::event_handler::{Error, EventHandler}; use crate::fetcher::{EventsFetcher, LastFinalizedBlockNumFetcher}; -use crate::primitives::GetEventId; use crate::sync_checkpoint_repository::{Checkpoint, CheckpointRepository}; +use primitives::GetEventId; /// Component, used to listen to chain and execute requested intents /// Requires specific implementations of: diff --git a/tee-worker/omni-executor/executor-core/src/native_call.rs b/tee-worker/omni-executor/executor-core/src/native_call.rs new file mode 100644 index 0000000000..2330f83017 --- /dev/null +++ b/tee-worker/omni-executor/executor-core/src/native_call.rs @@ -0,0 +1,24 @@ +use heima_authentication::auth_token::AuthOptions; +use parity_scale_codec::{Decode, Encode}; +use primitives::Identity; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum NativeCall { + request_auth_token(Identity, AuthOptions), + noop(Identity), +} + +impl NativeCall { + pub fn sender_identity(&self) -> &Identity { + match self { + NativeCall::request_auth_token(sender_identity, ..) => sender_identity, + NativeCall::noop(sender_identity) => sender_identity, + } + } + + pub fn signature_message_prefix(&self) -> String { + // TODO: update this when adding request_batch_vc variant + "Token: ".to_string() + } +} diff --git a/tee-worker/omni-executor/executor-core/src/primitives.rs b/tee-worker/omni-executor/executor-core/src/primitives.rs index 81ed8d504c..aa5335e38e 100644 --- a/tee-worker/omni-executor/executor-core/src/primitives.rs +++ b/tee-worker/omni-executor/executor-core/src/primitives.rs @@ -20,7 +20,3 @@ pub enum Intent { CallEthereum([u8; 20], Vec), TransferSolana([u8; 32], u64), // (to_pubkey, lamports) } - -pub trait GetEventId { - fn get_event_id(&self) -> Id; -} diff --git a/tee-worker/omni-executor/executor-core/src/storage.rs b/tee-worker/omni-executor/executor-core/src/storage.rs deleted file mode 100644 index 298be30295..0000000000 --- a/tee-worker/omni-executor/executor-core/src/storage.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -pub trait Storage { - fn get(&self, key: &K) -> Option; - fn insert(&self, key: K, value: V) -> Result<(), ()>; - fn remove(&self, key: &K) -> Result<(), ()>; - fn contains_key(&self, key: &K) -> bool; -} diff --git a/tee-worker/omni-executor/executor-crypto/Cargo.toml b/tee-worker/omni-executor/executor-crypto/Cargo.toml new file mode 100644 index 0000000000..8a848c31db --- /dev/null +++ b/tee-worker/omni-executor/executor-crypto/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "executor-crypto" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition.workspace = true + +[dependencies] +jsonwebtoken = { workspace = true } +log = { workspace = true } +parity-scale-codec = { workspace = true } +rand = { workspace = true } +ring = { workspace = true } +rsa = { workspace = true, features = ["sha2"] } +secp256k1 = { workspace = true, features = ["std", "global-context", "recovery"] } +serde = { workspace = true } +sp-core = { workspace = true } + +[lints] +workspace = true diff --git a/tee-worker/omni-executor/executor-crypto/src/aes256.rs b/tee-worker/omni-executor/executor-crypto/src/aes256.rs new file mode 100644 index 0000000000..5d59550add --- /dev/null +++ b/tee-worker/omni-executor/executor-crypto/src/aes256.rs @@ -0,0 +1,113 @@ +use parity_scale_codec::{Decode, Encode}; +use rand::Rng; +use ring::{ + aead::{ + Aad, BoundKey, LessSafeKey, Nonce, NonceSequence, SealingKey, UnboundKey, AES_256_GCM, + NONCE_LEN, + }, + error::Unspecified, +}; +use std::vec::Vec; + +// we use 256-bit AES-GCM as request enc/dec key +pub const AES_KEY_LEN: usize = 32; + +pub type Aes256Key = [u8; AES_KEY_LEN]; +pub type Aes256KeyNonce = [u8; NONCE_LEN]; + +// all-in-one struct containing the encrypted ciphertext with other +// metadata that is required for decryption +// +// by default a postfix tag is used => last 16 bytes of ciphertext is MAC tag +#[derive(Debug, Default, Clone, Eq, PartialEq, Encode, Decode)] +pub struct AesOutput { + pub ciphertext: Vec, + pub aad: Vec, + pub nonce: Aes256KeyNonce, // IV +} + +// Returns the default if any error happens +// We don't propagate the error to upper level as this function is used in too many places, +// it's too verbose to handle them all and pass back to the parentchain as events. +// We rely on the parentchain event consumers to handle them correctly (and they kind of +// have to, because they'll find all fields are 0) +pub fn aes_encrypt_default(key: &Aes256Key, data: &[u8]) -> AesOutput { + let mut in_out = data.to_vec(); + + let mut nonce = RingAeadNonceSequence::new(); + if nonce.advance().is_ok() { + let aad = b""; + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let mut sealing_key = SealingKey::new(unbound_key, nonce.clone()); + if sealing_key.seal_in_place_append_tag(Aad::from(aad), &mut in_out).is_ok() { + return AesOutput { + ciphertext: in_out.to_vec(), + aad: aad.to_vec(), + nonce: nonce.nonce, + }; + } + } + } + + AesOutput::default() +} + +// use LessSafeKey::seal_in_place_append_tag to encrypt the data using the given nonce +// don't be scared by the name, it's similar to `SealingKey::seal_in_place_append_tag`, +// except that it accepts an arbitrary nonce. +// It's only used by the one-off verification message calculation. +pub fn aes_encrypt_nonce(key: &Aes256Key, data: &[u8], nonce: Aes256KeyNonce) -> AesOutput { + let mut in_out = data.to_vec(); + let aad = b""; + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let less_safe_key = LessSafeKey::new(unbound_key); + if less_safe_key + .seal_in_place_append_tag( + Nonce::assume_unique_for_key(nonce), + Aad::from(aad), + &mut in_out, + ) + .is_ok() + { + return AesOutput { ciphertext: in_out.to_vec(), aad: aad.to_vec(), nonce }; + } + } + + AesOutput::default() +} + +pub fn aes_decrypt(key: &Aes256Key, data: &mut AesOutput) -> Option> { + let in_out = data.ciphertext.as_mut(); + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let less_safe_key = LessSafeKey::new(unbound_key); + return less_safe_key + .open_in_place( + Nonce::assume_unique_for_key(data.nonce), + Aad::from(data.aad.clone()), + in_out, + ) + .ok() + .map(|data| data.to_vec()); + } + None +} + +#[derive(Clone)] +struct RingAeadNonceSequence { + pub nonce: Aes256KeyNonce, +} + +impl RingAeadNonceSequence { + fn new() -> RingAeadNonceSequence { + RingAeadNonceSequence { nonce: [0u8; NONCE_LEN] } + } +} + +impl NonceSequence for RingAeadNonceSequence { + fn advance(&mut self) -> core::result::Result { + let nonce = Nonce::assume_unique_for_key(self.nonce); + let nonce_vec = rand::thread_rng().gen::(); + self.nonce.copy_from_slice(&nonce_vec[0..NONCE_LEN]); + Ok(nonce) + } +} diff --git a/tee-worker/omni-executor/executor-crypto/src/jwt.rs b/tee-worker/omni-executor/executor-crypto/src/jwt.rs new file mode 100644 index 0000000000..0f65dc133d --- /dev/null +++ b/tee-worker/omni-executor/executor-crypto/src/jwt.rs @@ -0,0 +1,39 @@ +use jsonwebtoken::{decode as decode_jwt, encode, DecodingKey, EncodingKey, Header, Validation}; +use serde::{de::DeserializeOwned, Serialize}; + +pub fn create(claims: &T, secret: &[u8]) -> Result { + encode(&Header::default(), claims, &EncodingKey::from_secret(secret)).map_err(|e| { + log::error!("Failed to encode token: {:?}", e); + e.to_string() + }) +} + +pub fn decode(token: &str, secret: &[u8]) -> Result { + let mut validation = Validation::default(); + validation.set_required_spec_claims(&["sub"]); + validation.validate_exp = false; + decode_jwt::(token, &DecodingKey::from_secret(secret), &validation) + .map(|data| data.claims) + .map_err(|e| e.to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)] + struct JwtClaims { + pub sub: String, + } + + #[test] + fn test_jwt() { + let secret = b"secret"; + let claims = JwtClaims { sub: "test".to_string() }; + + let token = create(&claims, secret).unwrap(); + let decoded = decode::(&token, secret).unwrap(); + + assert_eq!(claims, decoded); + } +} diff --git a/tee-worker/omni-executor/executor-crypto/src/lib.rs b/tee-worker/omni-executor/executor-crypto/src/lib.rs new file mode 100644 index 0000000000..e617bcbaef --- /dev/null +++ b/tee-worker/omni-executor/executor-crypto/src/lib.rs @@ -0,0 +1,7 @@ +pub mod aes256; +pub mod jwt; +pub mod secp256k1; +pub mod traits; + +pub use rsa; +pub use sp_core::{crypto::Pair as PairTrait, ecdsa, ed25519, hashing, sr25519, ByteArray}; diff --git a/tee-worker/omni-executor/executor-crypto/src/secp256k1.rs b/tee-worker/omni-executor/executor-crypto/src/secp256k1.rs new file mode 100644 index 0000000000..1ea35d99b2 --- /dev/null +++ b/tee-worker/omni-executor/executor-crypto/src/secp256k1.rs @@ -0,0 +1,77 @@ +// This code is copied from `sp-io` crate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub use secp256k1::Secp256k1; +use secp256k1::{ + ecdsa::{RecoverableSignature, RecoveryId}, + Message, SECP256K1, +}; + +/// Error verifying ECDSA signature +pub enum EcdsaVerifyError { + /// Incorrect value of R or S + BadRS, + /// Incorrect value of V + BadV, + /// Invalid signature + BadSignature, +} + +/// Verify and recover a SECP256k1 ECDSA signature. +/// +/// - `sig` is passed in RSV format. V should be either `0/1` or `27/28`. +/// - `msg` is the blake2-256 hash of the message. +/// +/// Returns `Err` if the signature is bad, otherwise the 64-byte pubkey +/// (doesn't include the 0x04 prefix). +pub fn secp256k1_ecdsa_recover( + sig: &[u8; 65], + msg: &[u8; 32], +) -> Result<[u8; 64], EcdsaVerifyError> { + let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32) + .map_err(|_| EcdsaVerifyError::BadV)?; + let sig = + RecoverableSignature::from_compact(&sig[..64], rid).map_err(|_| EcdsaVerifyError::BadRS)?; + let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed"); + let pubkey = SECP256K1 + .recover_ecdsa(&msg, &sig) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + let mut res = [0u8; 64]; + res.copy_from_slice(&pubkey.serialize_uncompressed()[1..]); + Ok(res) +} + +/// Verify and recover a SECP256k1 ECDSA signature. +/// +/// - `sig` is passed in RSV format. V should be either `0/1` or `27/28`. +/// - `msg` is the blake2-256 hash of the message. +/// +/// Returns `Err` if the signature is bad, otherwise the 33-byte compressed pubkey. +pub fn secp256k1_ecdsa_recover_compressed( + sig: &[u8; 65], + msg: &[u8; 32], +) -> Result<[u8; 33], EcdsaVerifyError> { + let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32) + .map_err(|_| EcdsaVerifyError::BadV)?; + let sig = + RecoverableSignature::from_compact(&sig[..64], rid).map_err(|_| EcdsaVerifyError::BadRS)?; + let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed"); + let pubkey = SECP256K1 + .recover_ecdsa(&msg, &sig) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + Ok(pubkey.serialize()) +} diff --git a/tee-worker/omni-executor/executor-crypto/src/traits.rs b/tee-worker/omni-executor/executor-crypto/src/traits.rs new file mode 100644 index 0000000000..3d3fe8b2c3 --- /dev/null +++ b/tee-worker/omni-executor/executor-crypto/src/traits.rs @@ -0,0 +1,12 @@ +use std::fmt::Debug; +use std::vec::Vec; + +pub trait Encrypt { + type Error: Debug; + fn encrypt(&self, data: &[u8]) -> Result, Self::Error>; +} + +pub trait Decrypt { + type Error: Debug; + fn decrypt(&self, data: &[u8]) -> Result, Self::Error>; +} diff --git a/tee-worker/omni-executor/parentchain/storage/Cargo.toml b/tee-worker/omni-executor/executor-storage/Cargo.toml similarity index 87% rename from tee-worker/omni-executor/parentchain/storage/Cargo.toml rename to tee-worker/omni-executor/executor-storage/Cargo.toml index 5a074c6cab..2c050abbd7 100644 --- a/tee-worker/omni-executor/parentchain/storage/Cargo.toml +++ b/tee-worker/omni-executor/executor-storage/Cargo.toml @@ -1,20 +1,21 @@ [package] -name = "parentchain-storage" +name = "executor-storage" version = "0.1.0" authors = ['Trust Computing GmbH '] edition.workspace = true [dependencies] +frame-support = { workspace = true, features = ["std"] } log = { workspace = true } parity-scale-codec = { workspace = true, features = ["derive"] } rocksdb = "0.23.0" +sp-state-machine = { workspace = true, features = ["std"] } subxt-core = { workspace = true } -executor-core = { workspace = true } -frame-support = { workspace = true, features = ["std"] } +# Local dependencies parentchain-api-interface = { workspace = true } parentchain-rpc-client = { workspace = true } -sp-state-machine = { workspace = true, features = ["std"] } +primitives = { workspace = true } [dev-dependencies] env_logger = { workspace = true } diff --git a/tee-worker/omni-executor/parentchain/storage/src/account_store.rs b/tee-worker/omni-executor/executor-storage/src/account_store.rs similarity index 57% rename from tee-worker/omni-executor/parentchain/storage/src/account_store.rs rename to tee-worker/omni-executor/executor-storage/src/account_store.rs index 19e58800fa..5f6b07fc3d 100644 --- a/tee-worker/omni-executor/parentchain/storage/src/account_store.rs +++ b/tee-worker/omni-executor/executor-storage/src/account_store.rs @@ -1,33 +1,29 @@ -use executor_core::storage::Storage; +use crate::Storage; use parentchain_api_interface::omni_account::storage::types::account_store::AccountStore; use parity_scale_codec::{Decode, Encode}; +use primitives::AccountId; use rocksdb::DB; -use std::path::Path; -use subxt_core::utils::AccountId32 as AccountId; +use std::sync::Arc; -const STORAGE_NAME: &str = "account_store_storage"; +const STORAGE_NAME: &[u8; 21] = b"account_store_storage"; pub struct AccountStoreStorage { - db: DB, + db: Arc, } impl AccountStoreStorage { - pub fn new() -> Self { - Self::default() + pub fn new(db: Arc) -> Self { + Self { db } } -} -impl Default for AccountStoreStorage { - fn default() -> Self { - let path = Path::new(crate::STORAGE_PATH).join(STORAGE_NAME); - let db = DB::open_default(path).expect("Failed to open database"); - Self { db } + fn storage_key(account_id: &AccountId) -> Vec { + (STORAGE_NAME, account_id).encode() } } impl Storage for AccountStoreStorage { fn get(&self, account_id: &AccountId) -> Option { - match self.db.get(account_id.encode()) { + match self.db.get(Self::storage_key(account_id)) { Ok(Some(value)) => AccountStore::decode(&mut &value[..]) .map_err(|e| { log::error!("Error decoding value from storage: {:?}", e); @@ -42,18 +38,20 @@ impl Storage for AccountStoreStorage { } fn insert(&self, account_id: AccountId, account_store: AccountStore) -> Result<(), ()> { - self.db.put(account_id.encode(), account_store.encode()).map_err(|e| { - log::error!("Error inserting value into storage: {:?}", e); - }) + self.db + .put(Self::storage_key(&account_id), account_store.encode()) + .map_err(|e| { + log::error!("Error inserting value into storage: {:?}", e); + }) } fn remove(&self, account_id: &AccountId) -> Result<(), ()> { - self.db.delete(account_id.encode()).map_err(|e| { + self.db.delete(Self::storage_key(account_id)).map_err(|e| { log::error!("Error removing value from storage: {:?}", e); }) } fn contains_key(&self, account_id: &AccountId) -> bool { - self.db.key_may_exist(account_id.encode()) + self.db.key_may_exist(Self::storage_key(account_id)) } } diff --git a/tee-worker/omni-executor/parentchain/storage/src/lib.rs b/tee-worker/omni-executor/executor-storage/src/lib.rs similarity index 62% rename from tee-worker/omni-executor/parentchain/storage/src/lib.rs rename to tee-worker/omni-executor/executor-storage/src/lib.rs index 2b53ddacac..0671ccd5e4 100644 --- a/tee-worker/omni-executor/parentchain/storage/src/lib.rs +++ b/tee-worker/omni-executor/executor-storage/src/lib.rs @@ -1,7 +1,10 @@ +mod member_omni_account; +pub use member_omni_account::MemberOmniAccountStorage; +mod verification_code; +pub use verification_code::VerificationCodeStorage; mod account_store; pub use account_store::AccountStoreStorage; -use executor_core::storage::Storage; use frame_support::sp_runtime::traits::BlakeTwo256; use frame_support::storage::storage_prefix; use parentchain_api_interface::omni_account::storage::types::account_store::AccountStore; @@ -9,23 +12,42 @@ use parentchain_rpc_client::{ CustomConfig, SubstrateRpcClient, SubstrateRpcClientFactory, SubxtClient, SubxtClientFactory, }; use parity_scale_codec::Decode; +use primitives::{AccountId, MemberAccount, TryFromSubxtType}; +use rocksdb::DB; use sp_state_machine::{read_proof_check, StorageProof}; -use subxt_core::utils::AccountId32 as AccountId; +use std::sync::Arc; -const STORAGE_PATH: &str = "storage_db"; +const STORAGE_DB_PATH: &str = "storage_db"; -pub async fn init_storage(ws_rpc_endpoint: &str) -> Result<(), ()> { +pub type StorageDB = DB; + +pub trait Storage { + fn get(&self, key: &K) -> Option; + fn insert(&self, key: K, value: V) -> Result<(), ()>; + fn remove(&self, key: &K) -> Result<(), ()>; + fn contains_key(&self, key: &K) -> bool; +} + +pub async fn init_storage(ws_rpc_endpoint: &str) -> Result, ()> { + let db = Arc::new(StorageDB::open_default(STORAGE_DB_PATH).map_err(|e| { + log::error!("Could not open db: {:?}", e); + })?); let client_factory: SubxtClientFactory = SubxtClientFactory::new(ws_rpc_endpoint); let mut client = client_factory.new_client().await.map_err(|e| { log::error!("Could not create client: {:?}", e); })?; - init_account_store_storage(&mut client).await?; + init_omni_account_storages(&mut client, db.clone()).await?; - Ok(()) + Ok(db) } -async fn init_account_store_storage(client: &mut SubxtClient) -> Result<(), ()> { +async fn init_omni_account_storages( + client: &mut SubxtClient, + storage_db: Arc, +) -> Result<(), ()> { + let account_store_storage = AccountStoreStorage::new(storage_db.clone()); + let member_omni_account_storage = MemberOmniAccountStorage::new(storage_db.clone()); let account_store_key_prefix = storage_prefix(b"OmniAccount", b"AccountStore"); let page_size = 300; let mut start_key: Option> = None; @@ -64,11 +86,11 @@ async fn init_account_store_storage(client: &mut SubxtClient) -> R .map_err(|e| { log::error!("Could not read proof check: {:?}", e); })?; - let account_store_storage = AccountStoreStorage::new(); + for key in storage_keys_paged.iter() { match storage_map.get(key) { Some(Some(value)) => { - let account_id: AccountId = extract_account_id_from_storage_key(key)?; + let omni_account: AccountId = extract_account_id_from_storage_key(key)?; let maybe_storage_value = client .storage() .at_latest() @@ -82,17 +104,29 @@ async fn init_account_store_storage(client: &mut SubxtClient) -> R log::error!("Could not fetch storage value: {:?}", e); })?; let Some(storage_value) = maybe_storage_value else { - log::error!("Storage value not found for account_id: {:?}", account_id); + log::error!("Storage value not found for account_id: {:?}", omni_account); return Err(()); }; if storage_value != *value { - log::error!("Storage value mismatch for account_id: {:?}", account_id); + log::error!("Storage value mismatch for account_id: {:?}", omni_account); return Err(()); } - let account_store = AccountStore::decode(&mut &value[..]).map_err(|e| { - log::error!("Error decoding account store: {:?}", e); - })?; - account_store_storage.insert(account_id, account_store).map_err(|e| { + let account_store: AccountStore = + Decode::decode(&mut &value[..]).map_err(|e| { + log::error!("Error decoding account store: {:?}", e); + })?; + for member in account_store.0.iter() { + let member_account = + MemberAccount::try_from_subxt_type(member).map_err(|e| { + log::error!("Error decoding member account: {:?}", e); + })?; + member_omni_account_storage + .insert(member_account.hash(), omni_account.clone()) + .map_err(|e| { + log::error!("Error inserting member account hash: {:?}", e); + })?; + } + account_store_storage.insert(omni_account, account_store).map_err(|e| { log::error!("Error inserting account store: {:?}", e); })?; }, diff --git a/tee-worker/omni-executor/executor-storage/src/member_omni_account.rs b/tee-worker/omni-executor/executor-storage/src/member_omni_account.rs new file mode 100644 index 0000000000..87e64d84e4 --- /dev/null +++ b/tee-worker/omni-executor/executor-storage/src/member_omni_account.rs @@ -0,0 +1,51 @@ +use crate::Storage; +use parity_scale_codec::{Decode, Encode}; +use primitives::{AccountId, Hash}; +use rocksdb::DB; +use std::sync::Arc; + +const STORAGE_NAME: &[u8; 19] = b"member_omni_account"; + +pub struct MemberOmniAccountStorage { + db: Arc, +} + +impl MemberOmniAccountStorage { + pub fn new(db: Arc) -> Self { + Self { db } + } + + fn storage_key(member_identity: &Hash) -> Vec { + (STORAGE_NAME, member_identity).encode() + } +} + +impl Storage for MemberOmniAccountStorage { + fn get(&self, member_identity: &Hash) -> Option { + match self.db.get(Self::storage_key(member_identity)) { + Ok(Some(value)) => AccountId::decode(&mut &value[..]).ok(), + _ => { + log::error!("Error getting member_account_hash from storage"); + None + }, + } + } + + fn insert(&self, member_identity: Hash, omni_account: AccountId) -> Result<(), ()> { + self.db + .put(Self::storage_key(&member_identity), omni_account.encode()) + .map_err(|e| { + log::error!("Error inserting member_account_hash into storage: {:?}", e); + }) + } + + fn remove(&self, member_identity: &Hash) -> Result<(), ()> { + self.db.delete(Self::storage_key(member_identity)).map_err(|e| { + log::error!("Error removing member_account_hash from storage: {:?}", e); + }) + } + + fn contains_key(&self, member_identity: &Hash) -> bool { + self.db.key_may_exist(Self::storage_key(member_identity)) + } +} diff --git a/tee-worker/omni-executor/executor-storage/src/verification_code.rs b/tee-worker/omni-executor/executor-storage/src/verification_code.rs new file mode 100644 index 0000000000..16cdbb5266 --- /dev/null +++ b/tee-worker/omni-executor/executor-storage/src/verification_code.rs @@ -0,0 +1,49 @@ +use crate::Storage; +use parity_scale_codec::{Decode, Encode}; +use primitives::Hash; +use rocksdb::DB; +use std::sync::Arc; + +const STORAGE_NAME: &[u8; 25] = b"verification_code_storage"; + +pub struct VerificationCodeStorage { + db: Arc, +} + +impl VerificationCodeStorage { + pub fn new(db: Arc) -> Self { + Self { db } + } + + fn storage_key(identity_hash: &Hash) -> Vec { + (STORAGE_NAME, identity_hash).encode() + } +} + +impl Storage for VerificationCodeStorage { + fn get(&self, identity_hash: &Hash) -> Option { + match self.db.get(Self::storage_key(identity_hash)) { + Ok(Some(value)) => String::decode(&mut &value[..]).ok(), + _ => { + log::error!("Error getting verification_code from storage"); + None + }, + } + } + + fn insert(&self, identity_hash: Hash, code: String) -> Result<(), ()> { + self.db.put(Self::storage_key(&identity_hash), code.encode()).map_err(|e| { + log::error!("Error inserting verification_code into storage: {:?}", e); + }) + } + + fn remove(&self, identity_hash: &Hash) -> Result<(), ()> { + self.db.delete(Self::storage_key(identity_hash)).map_err(|e| { + log::error!("Error removing verification_code from storage: {:?}", e); + }) + } + + fn contains_key(&self, identity_hash: &Hash) -> bool { + self.db.key_may_exist(Self::storage_key(identity_hash)) + } +} diff --git a/tee-worker/omni-executor/executor-worker/Cargo.toml b/tee-worker/omni-executor/executor-worker/Cargo.toml index b60e35e89c..b24c93ea99 100644 --- a/tee-worker/omni-executor/executor-worker/Cargo.toml +++ b/tee-worker/omni-executor/executor-worker/Cargo.toml @@ -7,16 +7,22 @@ edition.workspace = true [dependencies] clap = { workspace = true, features = ["derive"] } env_logger = { workspace = true } -ethereum-intent-executor = { workspace = true } -executor-core = { workspace = true } hex = "0.4.3" log = { workspace = true } -parentchain-listener = { workspace = true } -parentchain-storage = { workspace = true } scale-encode = { workspace = true } serde_json = "1.0.127" -solana-intent-executor = { workspace = true } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] } +# Local dependencies +ethereum-intent-executor = { workspace = true } +executor-core = { workspace = true } +executor-storage = { workspace = true } +native-task-handler = { workspace = true } +parentchain-listener = { workspace = true } +parentchain-rpc-client = { workspace = true } +parentchain-signer = { workspace = true } +rpc-server = { workspace = true } +solana-intent-executor = { workspace = true } + [lints] workspace = true diff --git a/tee-worker/omni-executor/executor-worker/src/cli.rs b/tee-worker/omni-executor/executor-worker/src/cli.rs index 6825453e57..bdd84558d6 100644 --- a/tee-worker/omni-executor/executor-worker/src/cli.rs +++ b/tee-worker/omni-executor/executor-worker/src/cli.rs @@ -19,6 +19,7 @@ pub struct RunArgs { pub parentchain_url: String, pub ethereum_url: String, pub solana_url: String, + pub worker_rpc_port: String, #[arg(short, long, default_value = "0", value_name = "start block to sync from parentchain")] pub start_block: u64, #[arg( diff --git a/tee-worker/omni-executor/executor-worker/src/main.rs b/tee-worker/omni-executor/executor-worker/src/main.rs index e1a6536a7f..c51911af4c 100644 --- a/tee-worker/omni-executor/executor-worker/src/main.rs +++ b/tee-worker/omni-executor/executor-worker/src/main.rs @@ -18,9 +18,18 @@ use crate::cli::Cli; use clap::Parser; use cli::*; use ethereum_intent_executor::EthereumIntentExecutor; -use parentchain_storage::init_storage; +use executor_storage::{init_storage, StorageDB}; +use log::error; +use native_task_handler::{run_native_task_handler, ParentchainTxSigner, TaskHandlerContext}; +use parentchain_rpc_client::metadata::SubxtMetadataProvider; +use parentchain_rpc_client::{CustomConfig, SubxtClientFactory}; +use parentchain_signer::key_store::SubstrateKeyStore; +use parentchain_signer::TransactionSigner; +use rpc_server::{start_server as start_rpc_server, ShieldingKey}; use solana_intent_executor::SolanaIntentExecutor; +use std::env; use std::io::Write; +use std::sync::Arc; use std::thread; use std::thread::JoinHandle; use tokio::runtime::Handle; @@ -49,8 +58,50 @@ async fn main() -> Result<(), ()> { match cli.cmd { Commands::Run(args) => { - init_storage(&args.parentchain_url).await.expect("Could not initialize storage"); - listen_to_parentchain(args).await.unwrap(); + // TODO: move to config + let jwt_secret = env::var("JWT_SECRET").unwrap_or("secret".to_string()); + let storage_db = + init_storage(&args.parentchain_url).await.expect("Could not initialize storage"); + + let client_factory = SubxtClientFactory::::new(&args.parentchain_url); + let metadata_provider = Arc::new(SubxtMetadataProvider::new(client_factory.clone())); + let key_store = Arc::new(SubstrateKeyStore::new(args.keystore_path.clone())); + let parentchain_rpc_client_factory = Arc::new(client_factory); + let transaction_signer = Arc::new(TransactionSigner::new( + metadata_provider, + parentchain_rpc_client_factory.clone(), + key_store.clone(), + )); + let task_handler_context = TaskHandlerContext::new( + parentchain_rpc_client_factory.clone(), + transaction_signer.clone(), + storage_db.clone(), + jwt_secret.clone(), + ); + // TODO: make buffer size configurable + let buffer = 1024; + let native_task_sender = + run_native_task_handler(buffer, Arc::new(task_handler_context)).await; + // TODO: get mrenclave from quote + let mrenclave = [0u8; 32]; + + start_rpc_server( + &args.worker_rpc_port, + parentchain_rpc_client_factory, + ShieldingKey::new(), + Arc::new(native_task_sender), + storage_db.clone(), + mrenclave, + jwt_secret, + ) + .await + .map_err(|e| { + error!("Could not start server: {:?}", e); + })?; + + listen_to_parentchain(args, storage_db, transaction_signer, key_store) + .await + .unwrap(); match signal::ctrl_c().await { Ok(()) => {}, @@ -61,14 +112,20 @@ async fn main() -> Result<(), ()> { } }, Commands::GenKey(args) => { - let _ = parentchain_listener::get_signer(&args.keystore_path); + let key_store = Arc::new(SubstrateKeyStore::new(args.keystore_path)); + let _ = parentchain_signer::get_signer(key_store); }, } Ok(()) } -async fn listen_to_parentchain(args: RunArgs) -> Result, ()> { +async fn listen_to_parentchain( + args: RunArgs, + storage_db: Arc, + parentchain_tx_signer: Arc, + key_store: Arc, +) -> Result, ()> { let (_sub_stop_sender, sub_stop_receiver) = oneshot::channel(); let ethereum_intent_executor = EthereumIntentExecutor::new(&args.ethereum_url).map_err(|e| log::error!("{:?}", e))?; @@ -83,7 +140,9 @@ async fn listen_to_parentchain(args: RunArgs) -> Result, ()> { ethereum_intent_executor, solana_intent_executor, sub_stop_receiver, - &args.keystore_path, + storage_db, + parentchain_tx_signer, + key_store, &args.log_path, ) .await?; diff --git a/tee-worker/omni-executor/heima/authentication/Cargo.toml b/tee-worker/omni-executor/heima/authentication/Cargo.toml new file mode 100644 index 0000000000..cb9967a7a0 --- /dev/null +++ b/tee-worker/omni-executor/heima/authentication/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "heima-authentication" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition.workspace = true + +[dependencies] +log = { workspace = true } +parity-scale-codec = { workspace = true } +serde = { workspace = true } + +executor-crypto = { workspace = true } +primitives = { workspace = true } + +[lints] +workspace = true diff --git a/tee-worker/omni-executor/heima/authentication/src/auth_token.rs b/tee-worker/omni-executor/heima/authentication/src/auth_token.rs new file mode 100644 index 0000000000..6fd4bc50a9 --- /dev/null +++ b/tee-worker/omni-executor/heima/authentication/src/auth_token.rs @@ -0,0 +1,118 @@ +use executor_crypto::jwt; +use parity_scale_codec::{Decode, Encode}; +use primitives::BlockNumber; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, PartialEq)] +pub enum Error { + InvalidToken, + InvalidSignature, + ExpiredToken, + InvalidSubject, + Base64DecodeError, + JsonError, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct AuthOptions { + expires_at: BlockNumber, +} + +#[derive(PartialEq, Debug, Serialize, Deserialize)] +pub struct AuthTokenClaims { + sub: String, + pub exp: BlockNumber, +} + +impl AuthTokenClaims { + pub fn new(sub: String, options: AuthOptions) -> Self { + Self { sub, exp: options.expires_at } + } +} + +pub struct Validation { + pub sub: String, + pub current_block: BlockNumber, +} + +impl Validation { + pub fn new(sub: String, current_block: BlockNumber) -> Self { + Self { sub, current_block } + } + + pub fn validate(&self, claims: &AuthTokenClaims) -> Result<(), Error> { + if self.sub != claims.sub { + return Err(Error::InvalidSubject); + } + + if self.current_block > claims.exp { + return Err(Error::ExpiredToken); + } + + Ok(()) + } +} + +pub trait AuthTokenValidator { + fn validate(&self, secret: &[u8], validation: Validation) -> Result<(), Error>; +} + +impl AuthTokenValidator for String { + fn validate(&self, secret: &[u8], validation: Validation) -> Result<(), Error> { + jwt::decode::(self, secret) + .map_err(|_| Error::InvalidToken) + .and_then(|claims| validation.validate(&claims)) + } +} + +impl AuthTokenValidator for &str { + fn validate(&self, secret: &[u8], validation: Validation) -> Result<(), Error> { + jwt::decode::(self, secret) + .map_err(|_| Error::InvalidToken) + .and_then(|claims| validation.validate(&claims)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_auth_token() { + let secret = b"secret"; + let claims = AuthTokenClaims::new("test".to_string(), AuthOptions { expires_at: 100 }); + let token = jwt::create(&claims, secret).unwrap(); + + let current_block = 50; + let validation = Validation::new("test".to_string(), current_block); + let result = token.validate(secret, validation); + + assert_eq!(result, Ok(())); + } + + #[test] + fn test_auth_token_expired() { + let secret = b"secret"; + let claims = AuthTokenClaims::new("test".to_string(), AuthOptions { expires_at: 100 }); + let token = jwt::create(&claims, secret).unwrap(); + + let current_block = 150; + let validation = Validation::new("test".to_string(), current_block); + let result = token.validate(secret, validation); + + assert_eq!(result, Err(Error::ExpiredToken)); + } + + #[test] + fn test_auth_token_invalid_subject() { + let secret = b"secret"; + let claims = AuthTokenClaims::new("test".to_string(), AuthOptions { expires_at: 100 }); + let token = jwt::create(&claims, secret).unwrap(); + + let current_block = 50; + let validation = Validation::new("invalid-sub".to_string(), current_block); + let result = token.validate(secret, validation); + + assert_eq!(result, Err(Error::InvalidSubject)); + } +} diff --git a/tee-worker/omni-executor/heima/authentication/src/lib.rs b/tee-worker/omni-executor/heima/authentication/src/lib.rs new file mode 100644 index 0000000000..403a6a802f --- /dev/null +++ b/tee-worker/omni-executor/heima/authentication/src/lib.rs @@ -0,0 +1 @@ +pub mod auth_token; diff --git a/tee-worker/omni-executor/parentchain/primitives/Cargo.toml b/tee-worker/omni-executor/heima/identity-verification/Cargo.toml similarity index 50% rename from tee-worker/omni-executor/parentchain/primitives/Cargo.toml rename to tee-worker/omni-executor/heima/identity-verification/Cargo.toml index a1886dbbec..9f9b9c1002 100644 --- a/tee-worker/omni-executor/parentchain/primitives/Cargo.toml +++ b/tee-worker/omni-executor/heima/identity-verification/Cargo.toml @@ -1,11 +1,15 @@ [package] -name = "parentchain-primitives" +name = "heima-identity-verification" version = "0.1.0" authors = ['Trust Computing GmbH '] edition.workspace = true [dependencies] -executor-core = { workspace = true } +async-trait = { workspace = true } +log = { workspace = true } +rand = { workspace = true } +sendgrid = "0.23.0" + [lints] workspace = true diff --git a/tee-worker/omni-executor/heima/identity-verification/src/helpers.rs b/tee-worker/omni-executor/heima/identity-verification/src/helpers.rs new file mode 100644 index 0000000000..31bb272cc8 --- /dev/null +++ b/tee-worker/omni-executor/heima/identity-verification/src/helpers.rs @@ -0,0 +1,40 @@ +use rand::{thread_rng, Rng}; +use std::string::String; + +// This will be used for oauth2 authentication +#[allow(dead_code)] +pub(crate) fn generate_alphanumeric_otp(length: usize) -> String { + let mut rng = thread_rng(); + let charset: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let random_string: String = (0..length) + .map(|_| { + let idx = rng.gen_range(0..charset.len()); + charset[idx] as char + }) + .collect(); + + random_string +} + +pub(crate) fn generate_otp(length: usize) -> String { + let mut rng = rand::thread_rng(); + let otp: String = (0..length).map(|_| rng.gen_range(0..10).to_string()).collect(); + otp +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_random_string() { + let random_string = generate_alphanumeric_otp(128); + assert_eq!(random_string.len(), 128); + } + + #[test] + fn test_generate_otp() { + let otp = generate_otp(6); + assert_eq!(otp.len(), 6); + } +} diff --git a/tee-worker/omni-executor/heima/identity-verification/src/lib.rs b/tee-worker/omni-executor/heima/identity-verification/src/lib.rs new file mode 100644 index 0000000000..2ddab67c76 --- /dev/null +++ b/tee-worker/omni-executor/heima/identity-verification/src/lib.rs @@ -0,0 +1,2 @@ +mod helpers; +pub mod web2; diff --git a/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mailer/mod.rs b/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mailer/mod.rs new file mode 100644 index 0000000000..5e76abcad8 --- /dev/null +++ b/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mailer/mod.rs @@ -0,0 +1,54 @@ +pub mod template; + +use async_trait::async_trait; +use sendgrid::v3::{Content, Email, Message, Personalization, Sender}; + +#[derive(Debug)] +pub enum Error { + SendEmailFailed, +} + +#[derive(Debug)] +pub struct Mail { + pub to: String, + pub subject: String, + pub body: String, + pub content_type: String, +} + +#[async_trait] +pub trait MailerTrait { + async fn send(&self, mail: Mail) -> Result<(), Error>; +} + +pub struct Mailer { + api_key: String, + from_email: String, + from_name: String, +} + +impl Mailer { + pub fn new(api_key: String, from_email: String, from_name: String) -> Self { + Self { api_key, from_email, from_name } + } +} + +#[async_trait] +impl MailerTrait for Mailer { + async fn send(&self, mail: Mail) -> Result<(), Error> { + let from_email = Email::new(&self.from_email).set_name(&self.from_name); + let personalization = Personalization::new(Email::new(&mail.to)); + let content = Content::new().set_content_type(&mail.content_type).set_value(&mail.body); + let message = Message::new(from_email) + .set_subject(&mail.subject) + .add_content(content) + .add_personalization(personalization); + let sender = Sender::new(self.api_key.clone(), None); + sender.send(&message).await.map_err(|_| { + log::error!("Failed to send email"); + Error::SendEmailFailed + })?; + + Ok(()) + } +} diff --git a/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mailer/template.rs b/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mailer/template.rs new file mode 100644 index 0000000000..a0a3484ea7 --- /dev/null +++ b/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mailer/template.rs @@ -0,0 +1,77 @@ +pub const EMAIL_VERIFICATION_TEMPLATE: &str = r#" + + + + + + + + + + + Email verification + + + +
+ Please use this code to verify your email. +  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏ +
+
+
+ + + + +
+ + + + +
+

+ Email Verification +

+

+ Please use this code to verify your email. +

+
+
+

{{ verification_code }}

+
+
+
+
+
+ + +"#; diff --git a/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mod.rs b/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mod.rs new file mode 100644 index 0000000000..617ac1238b --- /dev/null +++ b/tee-worker/omni-executor/heima/identity-verification/src/web2/email/mod.rs @@ -0,0 +1,21 @@ +mod mailer; +pub use mailer::Mailer; + +pub fn generate_verification_code() -> String { + crate::helpers::generate_otp(6) +} + +pub async fn send_verification_email( + mailer: &impl mailer::MailerTrait, + to: String, + verification_code: String, +) -> Result<(), mailer::Error> { + let mail = mailer::Mail { + to, + subject: "Verify your email".to_string(), + body: mailer::template::EMAIL_VERIFICATION_TEMPLATE + .replace("{{ verification_code }}", &verification_code), + content_type: "text/html".to_string(), + }; + mailer.send(mail).await +} diff --git a/tee-worker/omni-executor/heima/identity-verification/src/web2/mod.rs b/tee-worker/omni-executor/heima/identity-verification/src/web2/mod.rs new file mode 100644 index 0000000000..aa5f45d477 --- /dev/null +++ b/tee-worker/omni-executor/heima/identity-verification/src/web2/mod.rs @@ -0,0 +1 @@ +pub mod email; diff --git a/tee-worker/omni-executor/native-task-handler/Cargo.toml b/tee-worker/omni-executor/native-task-handler/Cargo.toml new file mode 100644 index 0000000000..bbde53c240 --- /dev/null +++ b/tee-worker/omni-executor/native-task-handler/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "native-task-handler" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition.workspace = true + +[dependencies] +log = { workspace = true } +parity-scale-codec = { workspace = true } +tokio = { workspace = true } + +# Local dependencies +executor-core = { workspace = true } +executor-crypto = { workspace = true } +executor-storage = { workspace = true } +heima-authentication = { workspace = true } +parentchain-api-interface = { workspace = true } +parentchain-rpc-client = { workspace = true } +parentchain-signer = { workspace = true } +primitives = { workspace = true } + +[lints] +workspace = true diff --git a/tee-worker/omni-executor/native-task-handler/src/lib.rs b/tee-worker/omni-executor/native-task-handler/src/lib.rs new file mode 100644 index 0000000000..09ce966f30 --- /dev/null +++ b/tee-worker/omni-executor/native-task-handler/src/lib.rs @@ -0,0 +1,167 @@ +mod types; + +use executor_core::native_call::NativeCall; +use executor_crypto::jwt; +use executor_storage::{MemberOmniAccountStorage, Storage, StorageDB}; +use heima_authentication::auth_token::AuthTokenClaims; +use parentchain_rpc_client::{ + metadata::{Metadata, SubxtMetadataProvider}, + AccountId32, CustomConfig, SubstrateRpcClient, SubstrateRpcClientFactory, SubxtClient, + SubxtClientFactory, +}; +use parentchain_signer::{key_store::SubstrateKeyStore, TransactionSigner}; +use parity_scale_codec::Encode; +use primitives::{utils::hex::ToHexPrefixed, OmniAccountAuthType}; +use std::{marker::PhantomData, sync::Arc}; +use tokio::sync::{mpsc, oneshot}; +use types::{NativeCallError, NativeCallOk}; + +pub type ResponseSender = oneshot::Sender>; + +pub type NativeTaskSender = mpsc::Sender; + +type NativeCallResponse = Result; + +pub type ParentchainTxSigner = TransactionSigner< + SubstrateKeyStore, + SubxtClient, + SubxtClientFactory, + CustomConfig, + Metadata, + SubxtMetadataProvider, +>; + +pub struct NativeTask { + pub call: NativeCall, + pub auth_type: OmniAccountAuthType, + pub response_sender: ResponseSender, +} + +pub struct TaskHandlerContext< + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, +> { + pub parentchain_rpc_client_factory: Arc, + pub storage_db: Arc, + pub jwt_secret: String, + pub transaction_signer: Arc, + phantom_account_id: PhantomData, + phantom_header: PhantomData
, + phantom_rpc_client: PhantomData, +} + +impl< + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, + > TaskHandlerContext +{ + pub fn new( + parentchain_rpc_client_factory: Arc, + transaction_signer: Arc, + storage_db: Arc, + jwt_secret: String, + ) -> Self { + Self { + parentchain_rpc_client_factory, + transaction_signer, + storage_db, + jwt_secret, + phantom_account_id: PhantomData, + phantom_header: PhantomData, + phantom_rpc_client: PhantomData, + } + } +} + +pub async fn run_native_task_handler< + AccountId: Send + Sync + 'static, + Header: Send + Sync + 'static, + RpcClient: SubstrateRpcClient + Send + Sync + 'static, + RpcClientFactory: SubstrateRpcClientFactory + Send + Sync + 'static, +>( + buffer: usize, + ctx: Arc>, +) -> NativeTaskSender { + let (sender, mut receiver) = mpsc::channel::(buffer); + + tokio::spawn(async move { + while let Some(task) = receiver.recv().await { + handle_native_call(ctx.clone(), task.call, task.response_sender).await; + } + }); + + sender +} + +async fn handle_native_call< + AccountId: Send + Sync + 'static, + Header: Send + Sync + 'static, + RpcClient: SubstrateRpcClient + Send + Sync + 'static, + RpcClientFactory: SubstrateRpcClientFactory + Send + Sync + 'static, +>( + ctx: Arc>, + call: NativeCall, + response_sender: ResponseSender, +) { + match call { + NativeCall::request_auth_token(sender_identity, auth_options) => { + let member_omni_account_storage = MemberOmniAccountStorage::new(ctx.storage_db.clone()); + let Some(omni_account) = member_omni_account_storage.get(&sender_identity.hash()) + else { + let response = NativeCallResponse::Err(NativeCallError::UnauthorizedSender); + if response_sender.send(response.encode()).is_err() { + log::error!("Failed to send response"); + } + return; + }; + let claims = AuthTokenClaims::new(omni_account.to_hex(), auth_options); + let Ok(token) = jwt::create(&claims, ctx.jwt_secret.as_bytes()) else { + let response = NativeCallResponse::Err(NativeCallError::AuthTokenCreationFailed); + if response_sender.send(response.encode()).is_err() { + log::error!("Failed to send response"); + } + return; + }; + let auth_token_requested_call = parentchain_api_interface::tx() + .omni_account() + .auth_token_requested(AccountId32(omni_account.into()), claims.exp); + + let Ok(mut client) = ctx.parentchain_rpc_client_factory.new_client().await else { + let response = NativeCallResponse::Err(NativeCallError::InternalError); + if response_sender.send(response.encode()).is_err() { + log::error!("Failed to send response"); + } + return; + }; + + let signed_call = ctx.transaction_signer.sign(auth_token_requested_call).await; + + if client.submit_tx(&signed_call).await.is_err() { + let response = NativeCallResponse::Err(NativeCallError::InternalError); + if response_sender.send(response.encode()).is_err() { + log::error!("Failed to send response"); + } + return; + } + + let response = NativeCallResponse::Ok(NativeCallOk::AuthToken(token)); + + if response_sender.send(response.encode()).is_err() { + log::error!("Failed to send response"); + } + }, + _ => { + let response = NativeCallResponse::Err(NativeCallError::UnexpectedCall(format!( + "Unexpected call: {:?}", + call + ))); + if response_sender.send(response.encode()).is_err() { + log::error!("Failed to send response"); + } + }, + } +} diff --git a/tee-worker/omni-executor/native-task-handler/src/types.rs b/tee-worker/omni-executor/native-task-handler/src/types.rs new file mode 100644 index 0000000000..762e167ae4 --- /dev/null +++ b/tee-worker/omni-executor/native-task-handler/src/types.rs @@ -0,0 +1,14 @@ +use parity_scale_codec::{Decode, Encode}; + +#[derive(Encode, Decode, Debug, PartialEq, Eq)] +pub enum NativeCallOk { + AuthToken(String), +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub enum NativeCallError { + UnexpectedCall(String), + UnauthorizedSender, + AuthTokenCreationFailed, + InternalError, +} diff --git a/tee-worker/omni-executor/parentchain/api-interface/artifacts/metadata.scale b/tee-worker/omni-executor/parentchain/api-interface/artifacts/metadata.scale index 9a0123f4af..ab0627afe9 100644 Binary files a/tee-worker/omni-executor/parentchain/api-interface/artifacts/metadata.scale and b/tee-worker/omni-executor/parentchain/api-interface/artifacts/metadata.scale differ diff --git a/tee-worker/omni-executor/parentchain/api-interface/src/interface.rs b/tee-worker/omni-executor/parentchain/api-interface/src/interface.rs index 02970f218e..7b3a1691ad 100644 --- a/tee-worker/omni-executor/parentchain/api-interface/src/interface.rs +++ b/tee-worker/omni-executor/parentchain/api-interface/src/interface.rs @@ -1306,9 +1306,9 @@ pub mod api { "query_call_info", types::QueryCallInfo { call, len }, [ - 241u8, 99u8, 20u8, 13u8, 66u8, 154u8, 92u8, 20u8, 74u8, 63u8, 131u8, - 38u8, 39u8, 180u8, 22u8, 29u8, 152u8, 164u8, 140u8, 228u8, 132u8, - 151u8, 168u8, 205u8, 37u8, 9u8, 151u8, 132u8, 250u8, 234u8, 37u8, 60u8, + 30u8, 138u8, 178u8, 236u8, 178u8, 94u8, 119u8, 15u8, 47u8, 252u8, + 133u8, 50u8, 71u8, 85u8, 213u8, 75u8, 128u8, 119u8, 251u8, 136u8, 15u8, + 6u8, 205u8, 28u8, 67u8, 78u8, 77u8, 231u8, 42u8, 218u8, 233u8, 88u8, ], ) } @@ -1326,9 +1326,10 @@ pub mod api { "query_call_fee_details", types::QueryCallFeeDetails { call, len }, [ - 65u8, 214u8, 27u8, 187u8, 55u8, 78u8, 138u8, 216u8, 95u8, 170u8, 107u8, - 54u8, 103u8, 18u8, 151u8, 108u8, 230u8, 25u8, 250u8, 93u8, 63u8, 79u8, - 193u8, 72u8, 192u8, 156u8, 181u8, 178u8, 219u8, 182u8, 159u8, 109u8, + 91u8, 199u8, 237u8, 1u8, 171u8, 236u8, 142u8, 3u8, 244u8, 143u8, 170u8, + 142u8, 154u8, 104u8, 239u8, 96u8, 59u8, 15u8, 61u8, 176u8, 184u8, + 155u8, 115u8, 244u8, 91u8, 148u8, 16u8, 143u8, 218u8, 155u8, 213u8, + 50u8, ], ) } @@ -3051,9 +3052,9 @@ pub mod api { .hash(); runtime_metadata_hash == [ - 183u8, 138u8, 42u8, 179u8, 59u8, 74u8, 128u8, 72u8, 198u8, 22u8, 118u8, 108u8, - 83u8, 51u8, 110u8, 166u8, 196u8, 214u8, 209u8, 181u8, 118u8, 161u8, 177u8, 90u8, - 176u8, 3u8, 147u8, 130u8, 135u8, 204u8, 99u8, 164u8, + 181u8, 110u8, 158u8, 48u8, 59u8, 238u8, 71u8, 178u8, 177u8, 250u8, 161u8, 106u8, + 246u8, 14u8, 105u8, 58u8, 104u8, 55u8, 37u8, 103u8, 195u8, 184u8, 66u8, 89u8, + 103u8, 12u8, 63u8, 90u8, 134u8, 99u8, 4u8, 4u8, ] } pub mod omni_account { @@ -3088,11 +3089,14 @@ pub mod api { pub member_account_hash: dispatch_as_omni_account::MemberAccountHash, pub call: ::subxt::ext::subxt_core::alloc::boxed::Box, + pub auth_type: dispatch_as_omni_account::AuthType, } pub mod dispatch_as_omni_account { use super::runtime_types; pub type MemberAccountHash = ::subxt::ext::subxt_core::utils::H256; pub type Call = runtime_types::paseo_parachain_runtime::RuntimeCall; + pub type AuthType = + runtime_types::core_primitives::omni_account::OmniAccountAuthType; } impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for DispatchAsOmniAccount { const PALLET: &'static str = "OmniAccount"; @@ -3116,11 +3120,14 @@ pub mod api { pub struct DispatchAsSigned { pub member_account_hash: dispatch_as_signed::MemberAccountHash, pub call: ::subxt::ext::subxt_core::alloc::boxed::Box, + pub auth_type: dispatch_as_signed::AuthType, } pub mod dispatch_as_signed { use super::runtime_types; pub type MemberAccountHash = ::subxt::ext::subxt_core::utils::H256; pub type Call = runtime_types::paseo_parachain_runtime::RuntimeCall; + pub type AuthType = + runtime_types::core_primitives::omni_account::OmniAccountAuthType; } impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for DispatchAsSigned { const PALLET: &'static str = "OmniAccount"; @@ -3169,11 +3176,17 @@ pub mod api { )] pub struct AddAccount { pub member_account: add_account::MemberAccount, + pub permissions: add_account::Permissions, } pub mod add_account { use super::runtime_types; pub type MemberAccount = runtime_types::core_primitives::omni_account::MemberAccount; + pub type Permissions = ::core::option::Option< + ::subxt::ext::subxt_core::alloc::vec::Vec< + runtime_types::paseo_parachain_runtime::OmniAccountPermission, + >, + >; } impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for AddAccount { const PALLET: &'static str = "OmniAccount"; @@ -3322,6 +3335,64 @@ pub mod api { const PALLET: &'static str = "OmniAccount"; const CALL: &'static str = "intent_executed"; } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub struct SetPermissions { + pub member_account_hash: set_permissions::MemberAccountHash, + pub permissions: set_permissions::Permissions, + } + pub mod set_permissions { + use super::runtime_types; + pub type MemberAccountHash = ::subxt::ext::subxt_core::utils::H256; + pub type Permissions = ::subxt::ext::subxt_core::alloc::vec::Vec< + runtime_types::paseo_parachain_runtime::OmniAccountPermission, + >; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetPermissions { + const PALLET: &'static str = "OmniAccount"; + const CALL: &'static str = "set_permissions"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub struct AuthTokenRequested { + pub who: auth_token_requested::Who, + pub expires_at: auth_token_requested::ExpiresAt, + } + pub mod auth_token_requested { + use super::runtime_types; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type ExpiresAt = ::core::primitive::u32; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for AuthTokenRequested { + const PALLET: &'static str = "OmniAccount"; + const CALL: &'static str = "auth_token_requested"; + } } pub struct TransactionApi; impl TransactionApi { @@ -3329,6 +3400,7 @@ pub mod api { &self, member_account_hash: types::dispatch_as_omni_account::MemberAccountHash, call: types::dispatch_as_omni_account::Call, + auth_type: types::dispatch_as_omni_account::AuthType, ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< types::DispatchAsOmniAccount, > { @@ -3338,11 +3410,13 @@ pub mod api { types::DispatchAsOmniAccount { member_account_hash, call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), + auth_type, }, [ - 28u8, 35u8, 187u8, 134u8, 130u8, 163u8, 66u8, 195u8, 96u8, 40u8, 250u8, - 127u8, 123u8, 162u8, 24u8, 24u8, 116u8, 245u8, 229u8, 150u8, 24u8, - 25u8, 94u8, 79u8, 93u8, 72u8, 125u8, 223u8, 194u8, 12u8, 1u8, 249u8, + 168u8, 40u8, 73u8, 240u8, 237u8, 200u8, 52u8, 79u8, 85u8, 185u8, 156u8, + 111u8, 31u8, 193u8, 95u8, 55u8, 219u8, 105u8, 95u8, 128u8, 105u8, + 243u8, 243u8, 116u8, 248u8, 90u8, 189u8, 161u8, 107u8, 233u8, 245u8, + 26u8, ], ) } @@ -3350,6 +3424,7 @@ pub mod api { &self, member_account_hash: types::dispatch_as_signed::MemberAccountHash, call: types::dispatch_as_signed::Call, + auth_type: types::dispatch_as_signed::AuthType, ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( @@ -3358,11 +3433,13 @@ pub mod api { types::DispatchAsSigned { member_account_hash, call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), + auth_type, }, [ - 202u8, 55u8, 230u8, 236u8, 37u8, 199u8, 242u8, 155u8, 246u8, 205u8, - 233u8, 96u8, 162u8, 21u8, 66u8, 4u8, 39u8, 239u8, 39u8, 254u8, 144u8, - 6u8, 2u8, 127u8, 55u8, 53u8, 37u8, 26u8, 97u8, 49u8, 235u8, 189u8, + 126u8, 50u8, 166u8, 234u8, 160u8, 222u8, 75u8, 229u8, 48u8, 29u8, + 159u8, 3u8, 160u8, 197u8, 24u8, 25u8, 190u8, 231u8, 96u8, 99u8, 29u8, + 145u8, 229u8, 233u8, 225u8, 114u8, 97u8, 197u8, 48u8, 15u8, 90u8, + 150u8, ], ) } @@ -3386,15 +3463,17 @@ pub mod api { pub fn add_account( &self, member_account: types::add_account::MemberAccount, + permissions: types::add_account::Permissions, ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( "OmniAccount", "add_account", - types::AddAccount { member_account }, + types::AddAccount { member_account, permissions }, [ - 150u8, 189u8, 68u8, 161u8, 59u8, 95u8, 55u8, 22u8, 10u8, 97u8, 110u8, - 93u8, 234u8, 194u8, 37u8, 64u8, 186u8, 50u8, 135u8, 72u8, 153u8, 91u8, - 90u8, 23u8, 161u8, 9u8, 67u8, 229u8, 139u8, 207u8, 144u8, 191u8, + 144u8, 99u8, 144u8, 107u8, 29u8, 237u8, 161u8, 141u8, 0u8, 130u8, + 115u8, 4u8, 17u8, 227u8, 235u8, 154u8, 202u8, 33u8, 215u8, 124u8, 95u8, + 170u8, 229u8, 197u8, 180u8, 188u8, 209u8, 251u8, 175u8, 87u8, 16u8, + 165u8, ], ) } @@ -3487,6 +3566,41 @@ pub mod api { ], ) } + pub fn set_permissions( + &self, + member_account_hash: types::set_permissions::MemberAccountHash, + permissions: types::set_permissions::Permissions, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { + ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + "OmniAccount", + "set_permissions", + types::SetPermissions { member_account_hash, permissions }, + [ + 250u8, 24u8, 165u8, 101u8, 77u8, 223u8, 96u8, 176u8, 103u8, 22u8, 51u8, + 151u8, 204u8, 164u8, 101u8, 60u8, 226u8, 161u8, 35u8, 119u8, 250u8, + 66u8, 68u8, 164u8, 188u8, 8u8, 213u8, 216u8, 0u8, 128u8, 130u8, 5u8, + ], + ) + } + pub fn auth_token_requested( + &self, + who: types::auth_token_requested::Who, + expires_at: types::auth_token_requested::ExpiresAt, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { + ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + "OmniAccount", + "auth_token_requested", + types::AuthTokenRequested { who, expires_at }, + [ + 86u8, 8u8, 155u8, 175u8, 185u8, 11u8, 23u8, 58u8, 47u8, 215u8, 177u8, + 22u8, 223u8, 15u8, 107u8, 49u8, 159u8, 167u8, 221u8, 170u8, 224u8, + 189u8, 107u8, 220u8, 216u8, 29u8, 128u8, 177u8, 169u8, 178u8, 14u8, + 85u8, + ], + ) + } } } #[doc = "The `Event` enum of this pallet"] @@ -3634,11 +3748,14 @@ pub mod api { #[doc = "Some call is dispatched as omni-account origin"] pub struct DispatchedAsOmniAccount { pub who: dispatched_as_omni_account::Who, + pub auth_type: dispatched_as_omni_account::AuthType, pub result: dispatched_as_omni_account::Result, } pub mod dispatched_as_omni_account { use super::runtime_types; pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type AuthType = + runtime_types::core_primitives::omni_account::OmniAccountAuthType; pub type Result = ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>; } @@ -3660,11 +3777,14 @@ pub mod api { #[doc = "Some call is dispatched as signed origin"] pub struct DispatchedAsSigned { pub who: dispatched_as_signed::Who, + pub auth_type: dispatched_as_signed::AuthType, pub result: dispatched_as_signed::Result, } pub mod dispatched_as_signed { use super::runtime_types; pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type AuthType = + runtime_types::core_primitives::omni_account::OmniAccountAuthType; pub type Result = ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>; } @@ -3724,6 +3844,56 @@ pub mod api { const PALLET: &'static str = "OmniAccount"; const EVENT: &'static str = "IntentExecuted"; } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "Member permission set"] + pub struct AccountPermissionsSet { + pub who: account_permissions_set::Who, + pub member_account_hash: account_permissions_set::MemberAccountHash, + } + pub mod account_permissions_set { + use super::runtime_types; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type MemberAccountHash = ::subxt::ext::subxt_core::utils::H256; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for AccountPermissionsSet { + const PALLET: &'static str = "OmniAccount"; + const EVENT: &'static str = "AccountPermissionsSet"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "An auth token is requested"] + pub struct AuthTokenRequested { + pub who: auth_token_requested::Who, + pub expires_at: auth_token_requested::ExpiresAt, + } + pub mod auth_token_requested { + use super::runtime_types; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type ExpiresAt = ::core::primitive::u32; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for AuthTokenRequested { + const PALLET: &'static str = "OmniAccount"; + const EVENT: &'static str = "AuthTokenRequested"; + } } pub mod storage { use super::runtime_types; @@ -3742,6 +3912,14 @@ pub mod api { pub type MemberAccountHash = ::subxt::ext::subxt_core::utils::AccountId32; pub type Param0 = ::subxt::ext::subxt_core::utils::H256; } + pub mod member_account_permissions { + use super::runtime_types; + pub type MemberAccountPermissions = + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::paseo_parachain_runtime::OmniAccountPermission, + >; + pub type Param0 = ::subxt::ext::subxt_core::utils::H256; + } } pub struct StorageApi; impl StorageApi { @@ -3841,6 +4019,55 @@ pub mod api { ], ) } + #[doc = " A map between hash of MemberAccount and its permissions"] + pub fn member_account_permissions_iter( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::member_account_permissions::MemberAccountPermissions, + (), + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "OmniAccount", + "MemberAccountPermissions", + (), + [ + 119u8, 233u8, 243u8, 176u8, 52u8, 185u8, 224u8, 189u8, 195u8, 17u8, + 38u8, 215u8, 42u8, 28u8, 12u8, 138u8, 4u8, 60u8, 11u8, 241u8, 199u8, + 246u8, 170u8, 227u8, 151u8, 37u8, 166u8, 111u8, 240u8, 19u8, 156u8, + 50u8, + ], + ) + } + #[doc = " A map between hash of MemberAccount and its permissions"] + pub fn member_account_permissions( + &self, + _0: impl ::core::borrow::Borrow, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::member_account_permissions::Param0, + >, + types::member_account_permissions::MemberAccountPermissions, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "OmniAccount", + "MemberAccountPermissions", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new( + _0.borrow(), + ), + [ + 119u8, 233u8, 243u8, 176u8, 52u8, 185u8, 224u8, 189u8, 195u8, 17u8, + 38u8, 215u8, 42u8, 28u8, 12u8, 138u8, 4u8, 60u8, 11u8, 241u8, 199u8, + 246u8, 170u8, 227u8, 151u8, 37u8, 166u8, 111u8, 240u8, 19u8, 156u8, + 50u8, + ], + ) + } } } pub mod constants { @@ -3864,6 +4091,23 @@ pub mod api { ], ) } + #[doc = " The maximum number of permissions that a member account can have"] + pub fn max_permissions( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "OmniAccount", + "MaxPermissions", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } } } } @@ -4683,9 +4927,10 @@ pub mod api { "batch", types::Batch { calls }, [ - 216u8, 129u8, 96u8, 149u8, 91u8, 253u8, 52u8, 189u8, 152u8, 61u8, 34u8, - 198u8, 4u8, 12u8, 117u8, 214u8, 191u8, 85u8, 158u8, 13u8, 152u8, 115u8, - 160u8, 220u8, 235u8, 100u8, 161u8, 166u8, 174u8, 116u8, 35u8, 183u8, + 36u8, 189u8, 248u8, 135u8, 209u8, 177u8, 207u8, 46u8, 66u8, 249u8, + 183u8, 192u8, 155u8, 103u8, 210u8, 85u8, 183u8, 54u8, 240u8, 46u8, + 88u8, 140u8, 236u8, 168u8, 32u8, 145u8, 46u8, 229u8, 225u8, 6u8, 196u8, + 17u8, ], ) } @@ -6569,6 +6814,31 @@ pub mod api { ::subxt::ext::subxt_core::utils::H256, ), } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub enum OmniAccountAuthType { + #[codec(index = 0)] + Web3, + #[codec(index = 1)] + Email, + #[codec(index = 2)] + OAuth2, + #[codec(index = 3)] + AuthToken, + } } pub mod teebag { use super::runtime_types; @@ -7857,6 +8127,36 @@ pub mod api { After(_0), } } + pub mod tokens { + use super::runtime_types; + pub mod fungible { + use super::runtime_types; + pub mod union_of { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub enum NativeOrWithId<_0> { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + WithId(_0), + } + } + } + } } } pub mod frame_system { @@ -11975,6 +12275,8 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box< runtime_types::paseo_parachain_runtime::RuntimeCall, >, + auth_type: + runtime_types::core_primitives::omni_account::OmniAccountAuthType, }, #[codec(index = 1)] dispatch_as_signed { @@ -11982,6 +12284,8 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box< runtime_types::paseo_parachain_runtime::RuntimeCall, >, + auth_type: + runtime_types::core_primitives::omni_account::OmniAccountAuthType, }, #[codec(index = 2)] create_account_store { @@ -11990,6 +12294,11 @@ pub mod api { #[codec(index = 3)] add_account { member_account: runtime_types::core_primitives::omni_account::MemberAccount, + permissions: ::core::option::Option< + ::subxt::ext::subxt_core::alloc::vec::Vec< + runtime_types::paseo_parachain_runtime::OmniAccountPermission, + >, + >, }, #[codec(index = 4)] remove_accounts { @@ -12017,6 +12326,18 @@ pub mod api { intent: runtime_types::core_primitives::intent::Intent, result: runtime_types::pallet_omni_account::pallet::IntentExecutionResult, }, + #[codec(index = 9)] + set_permissions { + member_account_hash: ::subxt::ext::subxt_core::utils::H256, + permissions: ::subxt::ext::subxt_core::alloc::vec::Vec< + runtime_types::paseo_parachain_runtime::OmniAccountPermission, + >, + }, + #[codec(index = 10)] + auth_token_requested { + who: ::subxt::ext::subxt_core::utils::AccountId32, + expires_at: ::core::primitive::u32, + }, } #[derive( :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, @@ -12047,6 +12368,10 @@ pub mod api { UnknownAccountStore, #[codec(index = 5)] EmptyAccount, + #[codec(index = 6)] + NoPermission, + #[codec(index = 7)] + PermissionsLenLimitReached, } #[derive( :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, @@ -12100,6 +12425,8 @@ pub mod api { #[doc = "Some call is dispatched as omni-account origin"] DispatchedAsOmniAccount { who: ::subxt::ext::subxt_core::utils::AccountId32, + auth_type: + runtime_types::core_primitives::omni_account::OmniAccountAuthType, result: ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, }, @@ -12107,6 +12434,8 @@ pub mod api { #[doc = "Some call is dispatched as signed origin"] DispatchedAsSigned { who: ::subxt::ext::subxt_core::utils::AccountId32, + auth_type: + runtime_types::core_primitives::omni_account::OmniAccountAuthType, result: ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, }, @@ -12123,6 +12452,18 @@ pub mod api { intent: runtime_types::core_primitives::intent::Intent, result: runtime_types::pallet_omni_account::pallet::IntentExecutionResult, }, + #[codec(index = 9)] + #[doc = "Member permission set"] + AccountPermissionsSet { + who: ::subxt::ext::subxt_core::utils::AccountId32, + member_account_hash: ::subxt::ext::subxt_core::utils::H256, + }, + #[codec(index = 10)] + #[doc = "An auth token is requested"] + AuthTokenRequested { + who: ::subxt::ext::subxt_core::utils::AccountId32, + expires_at: ::core::primitive::u32, + }, } #[derive( :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, @@ -12164,6 +12505,97 @@ pub mod api { OmniAccountMembers(_0, ::core::primitive::u32, ::core::primitive::u32), } } + pub mod pallet_omni_bridge { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] + pub enum Call { + # [codec (index = 0)] set_admin { new_admin : :: subxt :: ext :: subxt_core :: utils :: AccountId32 , } , # [codec (index = 1)] pay_in { req : runtime_types :: pallet_omni_bridge :: PayInRequest < runtime_types :: frame_support :: traits :: tokens :: fungible :: union_of :: NativeOrWithId < :: core :: primitive :: u128 > , :: core :: primitive :: u128 > , } , # [codec (index = 2)] request_pay_out { req : runtime_types :: pallet_omni_bridge :: PayOutRequest < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , :: core :: primitive :: u128 > , aye : :: core :: primitive :: bool , } , # [codec (index = 3)] add_relayer { who : :: subxt :: ext :: subxt_core :: utils :: AccountId32 , } , # [codec (index = 4)] remove_relayer { who : :: subxt :: ext :: subxt_core :: utils :: AccountId32 , } , # [codec (index = 5)] set_pay_in_fee { asset : runtime_types :: frame_support :: traits :: tokens :: fungible :: union_of :: NativeOrWithId < :: core :: primitive :: u128 > , dest_chain : runtime_types :: pallet_omni_bridge :: ChainType , fee : :: core :: primitive :: u128 , } , # [codec (index = 6)] set_resource_id { resource_id : [:: core :: primitive :: u8 ; 32usize] , chain_asset : runtime_types :: pallet_omni_bridge :: ChainAsset < runtime_types :: frame_support :: traits :: tokens :: fungible :: union_of :: NativeOrWithId < :: core :: primitive :: u128 > > , } , # [codec (index = 7)] remove_resource_id { resource_id : [:: core :: primitive :: u8 ; 32usize] , } , # [codec (index = 8)] set_relayer_threshold { threshold : :: core :: primitive :: u32 , } , # [codec (index = 9)] add_pay_in_pair { asset : runtime_types :: frame_support :: traits :: tokens :: fungible :: union_of :: NativeOrWithId < :: core :: primitive :: u128 > , dest_chain : runtime_types :: pallet_omni_bridge :: ChainType , } , # [codec (index = 10)] remove_pay_in_pair { asset : runtime_types :: frame_support :: traits :: tokens :: fungible :: union_of :: NativeOrWithId < :: core :: primitive :: u128 > , dest_chain : runtime_types :: pallet_omni_bridge :: ChainType , } , } + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct ChainAsset<_0> { + pub chain: runtime_types::pallet_omni_bridge::ChainType, + pub asset: _0, + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub enum ChainType { + #[codec(index = 0)] + Heima, + #[codec(index = 1)] + Ethereum(::core::primitive::u32), + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct PayInRequest<_0, _1> { + pub asset: _0, + pub dest_chain: runtime_types::pallet_omni_bridge::ChainType, + pub dest_account: ::subxt::ext::subxt_core::alloc::vec::Vec<::core::primitive::u8>, + pub amount: _1, + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct PayOutRequest<_0, _1> { + pub source_chain: runtime_types::pallet_omni_bridge::ChainType, + pub nonce: ::core::primitive::u64, + pub resource_id: [::core::primitive::u8; 32usize], + pub dest_account: _0, + pub amount: _1, + } + } pub mod pallet_parachain_staking { use super::runtime_types; pub mod inflation { @@ -14420,6 +14852,29 @@ pub mod api { #[codec(dumb_trait_bound)] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub enum OmniAccountPermission { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AccountManagement, + #[codec(index = 2)] + RequestNativeIntent, + #[codec(index = 3)] + RequestEthereumIntent, + #[codec(index = 4)] + RequestSolanaIntent, + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: codec :: Decode, + :: subxt :: ext :: subxt_core :: ext :: codec :: Encode, + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + # [codec (crate = :: subxt :: ext :: subxt_core :: ext :: codec)] + #[codec(dumb_trait_bound)] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] pub enum OriginCaller { # [codec (index = 0)] system (runtime_types :: frame_support :: dispatch :: RawOrigin < :: subxt :: ext :: subxt_core :: utils :: AccountId32 > ,) , # [codec (index = 22)] Council (runtime_types :: pallet_collective :: RawOrigin < :: subxt :: ext :: subxt_core :: utils :: AccountId32 > ,) , # [codec (index = 24)] TechnicalCommittee (runtime_types :: pallet_collective :: RawOrigin < :: subxt :: ext :: subxt_core :: utils :: AccountId32 > ,) , # [codec (index = 51)] PolkadotXcm (runtime_types :: pallet_xcm :: pallet :: Origin ,) , # [codec (index = 52)] CumulusXcm (runtime_types :: cumulus_pallet_xcm :: pallet :: Origin ,) , # [codec (index = 73)] DeveloperCommittee (runtime_types :: pallet_collective :: RawOrigin < :: subxt :: ext :: subxt_core :: utils :: AccountId32 > ,) , # [codec (index = 84)] OmniAccount (runtime_types :: pallet_omni_account :: RawOrigin < :: subxt :: ext :: subxt_core :: utils :: AccountId32 > ,) , # [codec (index = 121)] Ethereum (runtime_types :: pallet_ethereum :: RawOrigin ,) , # [codec (index = 172)] Origins (runtime_types :: paseo_parachain_runtime :: governance_v2 :: origins :: pallet_custom_origins :: Origin ,) , # [codec (index = 9)] Void (runtime_types :: sp_core :: Void ,) , } #[derive( @@ -14553,6 +15008,8 @@ pub mod api { AssetsHandler(runtime_types::pallet_assets_handler::pallet::Call), #[codec(index = 84)] OmniAccount(runtime_types::pallet_omni_account::pallet::Call), + #[codec(index = 85)] + OmniBridge(runtime_types::pallet_omni_bridge::pallet::Call), #[codec(index = 93)] Teebag(runtime_types::pallet_teebag::pallet::Call), #[codec(index = 120)] diff --git a/tee-worker/omni-executor/parentchain/listener/Cargo.toml b/tee-worker/omni-executor/parentchain/listener/Cargo.toml index 2af275aca6..69ee4a9bdc 100644 --- a/tee-worker/omni-executor/parentchain/listener/Cargo.toml +++ b/tee-worker/omni-executor/parentchain/listener/Cargo.toml @@ -16,11 +16,13 @@ subxt-core = { workspace = true } subxt-signer = { workspace = true } tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } +# Local dependencies executor-core = { workspace = true } +executor-storage = { workspace = true } parentchain-api-interface = { workspace = true } -parentchain-primitives = { workspace = true } parentchain-rpc-client = { workspace = true } -parentchain-storage = { workspace = true } +parentchain-signer = { workspace = true } +primitives = { workspace = true } [dev-dependencies] env_logger = { workspace = true } diff --git a/tee-worker/omni-executor/parentchain/listener/src/event_handler.rs b/tee-worker/omni-executor/parentchain/listener/src/event_handler.rs index 16cf1e9048..e7651d8cfa 100644 --- a/tee-worker/omni-executor/parentchain/listener/src/event_handler.rs +++ b/tee-worker/omni-executor/parentchain/listener/src/event_handler.rs @@ -14,15 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::metadata::{MetadataProvider, SubxtMetadataProvider}; -use crate::transaction_signer::TransactionSigner; use async_trait::async_trait; use executor_core::event_handler::Error::RecoverableError; use executor_core::event_handler::{Error, EventHandler as EventHandlerTrait}; use executor_core::intent_executor::IntentExecutor; use executor_core::key_store::KeyStore; use executor_core::primitives::Intent; -use executor_core::storage::Storage; +use executor_storage::Storage; use log::error; use parentchain_api_interface::{ omni_account::{ @@ -33,8 +31,12 @@ use parentchain_api_interface::{ runtime_types::core_primitives::intent::Intent as RuntimeIntent, tx as parentchain_tx, }; -use parentchain_primitives::BlockEvent; -use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use parentchain_rpc_client::{ + metadata::{MetadataProvider, SubxtMetadataProvider}, + SubstrateRpcClient, SubstrateRpcClientFactory, +}; +use parentchain_signer::TransactionSigner; +use primitives::{AccountId, BlockEvent, Hash, MemberAccount, TryFromSubxtType}; use std::marker::PhantomData; use std::sync::Arc; use subxt::ext::scale_decode; @@ -53,7 +55,8 @@ pub struct EventHandler< KeyStoreT: KeyStore, RpcClient: SubstrateRpcClient, RpcClientFactory: SubstrateRpcClientFactory, - AccountStoreStorage: Storage, + AccountStoreStorage: Storage, + MemberOmniAccountStorage: Storage, > { metadata_provider: Arc, ethereum_intent_executor: EthereumIntentExecutorT, @@ -70,6 +73,7 @@ pub struct EventHandler< >, >, account_store_storage: Arc, + member_account_storage: Arc, phantom_data: PhantomData<(MetadataT, RpcClient)>, } @@ -82,7 +86,8 @@ impl< KeyStoreT: KeyStore, RpcClient: SubstrateRpcClient, RpcClientFactory: SubstrateRpcClientFactory, - AccountStoreStorage: Storage, + AccountStoreStorage: Storage, + MemberOmniAccountStorage: Storage, > EventHandler< ChainConfig, @@ -94,6 +99,7 @@ impl< RpcClient, RpcClientFactory, AccountStoreStorage, + MemberOmniAccountStorage, > { pub fn new( @@ -112,6 +118,7 @@ impl< >, >, account_store_storage: Arc, + member_account_storage: Arc, ) -> Self { Self { metadata_provider, @@ -120,6 +127,7 @@ impl< rpc_client_factory, transaction_signer, account_store_storage, + member_account_storage, phantom_data: Default::default(), } } @@ -140,7 +148,8 @@ impl< RpcClientFactory: SubstrateRpcClientFactory + Send + Sync, - AccountStoreStorage: Storage + Send + Sync, + AccountStoreStorage: Storage + Send + Sync, + MemberOmniAccountStorage: Storage + Send + Sync, > EventHandlerTrait for EventHandler< ChainConfig, @@ -152,6 +161,7 @@ impl< RpcClient, RpcClientFactory, AccountStoreStorage, + MemberOmniAccountStorage, > { async fn handle(&self, event: BlockEvent) -> Result<(), Error> { @@ -222,8 +232,24 @@ impl< Error::NonRecoverableError })?; + let omni_account = AccountId::new(account_store_updated.who.0); + + for member in account_store_updated.account_store.0.iter() { + let member_account = + MemberAccount::try_from_subxt_type(member).map_err(|e| { + log::error!("Error decoding member account: {:?}", e); + Error::NonRecoverableError + })?; + self.member_account_storage + .insert(member_account.hash(), omni_account.clone()) + .map_err(|e| { + log::error!("Error inserting member account hash: {:?}", e); + Error::NonRecoverableError + })?; + } + self.account_store_storage - .insert(account_store_updated.who, account_store_updated.account_store) + .insert(omni_account, account_store_updated.account_store) .map_err(|_| { log::error!("Could not insert account store into storage"); Error::NonRecoverableError diff --git a/tee-worker/omni-executor/parentchain/listener/src/fetcher.rs b/tee-worker/omni-executor/parentchain/listener/src/fetcher.rs index 23d7cb7506..6200ec41fc 100644 --- a/tee-worker/omni-executor/parentchain/listener/src/fetcher.rs +++ b/tee-worker/omni-executor/parentchain/listener/src/fetcher.rs @@ -17,9 +17,9 @@ use async_trait::async_trait; use executor_core::fetcher::{EventsFetcher, LastFinalizedBlockNumFetcher}; use log::error; -use parentchain_primitives::{BlockEvent, EventId}; use parentchain_rpc_client::SubstrateRpcClient; use parentchain_rpc_client::SubstrateRpcClientFactory; +use primitives::{BlockEvent, EventId}; use std::marker::PhantomData; use std::sync::Arc; @@ -75,7 +75,7 @@ impl< if let Some(ref mut client) = self.client { let block_num = client.get_last_finalized_block_num().await?; - Ok(Some(block_num)) + Ok(Some(block_num.into())) } else { Err(()) } diff --git a/tee-worker/omni-executor/parentchain/listener/src/lib.rs b/tee-worker/omni-executor/parentchain/listener/src/lib.rs index f7df846873..346eb4eada 100644 --- a/tee-worker/omni-executor/parentchain/listener/src/lib.rs +++ b/tee-worker/omni-executor/parentchain/listener/src/lib.rs @@ -16,37 +16,41 @@ mod event_handler; mod fetcher; -mod key_store; mod listener; -mod metadata; mod sync_checkpoint; -mod transaction_signer; use crate::event_handler::EventHandler; use crate::fetcher::Fetcher; -use crate::key_store::SubstrateKeyStore; use crate::listener::ParentchainListener; -use crate::metadata::SubxtMetadataProvider; -use crate::transaction_signer::TransactionSigner; use executor_core::intent_executor::IntentExecutor; -use executor_core::key_store::KeyStore; use executor_core::listener::Listener; use executor_core::sync_checkpoint_repository::FileCheckpointRepository; -use log::{error, info}; +use executor_storage::{AccountStoreStorage, MemberOmniAccountStorage, StorageDB}; +use log::error; use parentchain_api_interface::{ runtime_types::core_primitives::teebag::types::DcapProvider, teebag::calls::types::register_enclave::{AttestationType, WorkerMode, WorkerType}, }; -use parentchain_rpc_client::SubstrateRpcClient; -use parentchain_rpc_client::{CustomConfig, SubxtClient, SubxtClientFactory}; -use parentchain_storage::AccountStoreStorage; +use parentchain_rpc_client::{ + metadata::SubxtMetadataProvider, CustomConfig, SubstrateRpcClient, SubxtClient, + SubxtClientFactory, +}; +use parentchain_signer::{get_signer, key_store::SubstrateKeyStore, TransactionSigner}; use std::sync::Arc; -use subxt_core::utils::AccountId32; use subxt_core::Metadata; use subxt_signer::sr25519::Keypair; use tokio::runtime::Handle; use tokio::sync::oneshot::Receiver; +type ParentchainTxSigner = TransactionSigner< + SubstrateKeyStore, + SubxtClient, + SubxtClientFactory, + CustomConfig, + Metadata, + SubxtMetadataProvider, +>; + /// Creates parentchain listener #[allow(clippy::too_many_arguments)] pub async fn create_listener( @@ -56,7 +60,9 @@ pub async fn create_listener( ethereum_intent_executor: EthereumIntentExecutor, solana_intent_executor: SolanaIntentExecutor, stop_signal: Receiver<()>, - keystore_path: &str, + storage_db: Arc, + transaction_signer: Arc, + key_store: Arc, log_path: &str, ) -> Result< ParentchainListener< @@ -67,6 +73,7 @@ pub async fn create_listener( EthereumIntentExecutor, SolanaIntentExecutor, AccountStoreStorage, + MemberOmniAccountStorage, >, (), > @@ -83,17 +90,12 @@ where let metadata_provider = Arc::new(SubxtMetadataProvider::new(SubxtClientFactory::new(ws_rpc_endpoint))); - let (key_store, signer) = get_signer(keystore_path); - - let transaction_signer = Arc::new(TransactionSigner::new( - metadata_provider.clone(), - client_factory.clone(), - key_store.clone(), - )); + let signer = get_signer(key_store); perform_attestation(client_factory, signer, &transaction_signer).await?; - let account_store_storage = Arc::new(AccountStoreStorage::new()); + let account_store_storage = Arc::new(AccountStoreStorage::new(storage_db.clone())); + let member_account_storage = Arc::new(MemberOmniAccountStorage::new(storage_db.clone())); let event_handler = EventHandler::new( metadata_provider, @@ -102,29 +104,12 @@ where SubxtClientFactory::new(ws_rpc_endpoint), transaction_signer, account_store_storage, + member_account_storage, ); Listener::new(id, handle, fetcher, event_handler, stop_signal, last_processed_log_repository) } -pub fn get_signer(path: &str) -> (Arc, Keypair) { - let key_store = Arc::new(SubstrateKeyStore::new(path.to_string())); - let secret_key_bytes = key_store - .read() - .map_err(|e| { - error!("Could not unseal key: {:?}", e); - }) - .unwrap(); - let signer = subxt_signer::sr25519::Keypair::from_secret_key(secret_key_bytes) - .map_err(|e| { - error!("Could not create secret key: {:?}", e); - }) - .unwrap(); - - info!("Substrate signer address: {}", AccountId32::from(signer.public_key())); - (key_store, signer) -} - #[allow(unused_assignments, unused_mut, unused_variables, clippy::type_complexity)] async fn perform_attestation( client_factory: Arc>, @@ -145,6 +130,7 @@ async fn perform_attestation( #[cfg(feature = "gramine-quote")] { + use log::info; use std::fs; use std::fs::File; use std::io::Write; diff --git a/tee-worker/omni-executor/parentchain/listener/src/listener.rs b/tee-worker/omni-executor/parentchain/listener/src/listener.rs index 5a94427a04..c2bbe0227f 100644 --- a/tee-worker/omni-executor/parentchain/listener/src/listener.rs +++ b/tee-worker/omni-executor/parentchain/listener/src/listener.rs @@ -16,11 +16,11 @@ use crate::event_handler::EventHandler; use crate::fetcher::Fetcher; -use crate::key_store::SubstrateKeyStore; -use crate::metadata::SubxtMetadataProvider; use crate::sync_checkpoint::SyncCheckpoint; use executor_core::listener::Listener; -use parentchain_primitives::{BlockEvent, EventId}; +use parentchain_rpc_client::metadata::SubxtMetadataProvider; +use parentchain_signer::key_store::SubstrateKeyStore; +use primitives::{BlockEvent, EventId}; use subxt::Metadata; use subxt_core::Config; @@ -34,6 +34,7 @@ pub type ParentchainListener< EthereumIntentExecutor, SolanaIntentExecutor, AccountStoreStorage, + MemberAccountStorage, > = Listener< Fetcher< ::AccountId, @@ -55,5 +56,6 @@ pub type ParentchainListener< RpcClient, RpcClientFactory, AccountStoreStorage, + MemberAccountStorage, >, >; diff --git a/tee-worker/omni-executor/parentchain/listener/src/sync_checkpoint.rs b/tee-worker/omni-executor/parentchain/listener/src/sync_checkpoint.rs index ae8e606d81..9a8d2c8d9b 100644 --- a/tee-worker/omni-executor/parentchain/listener/src/sync_checkpoint.rs +++ b/tee-worker/omni-executor/parentchain/listener/src/sync_checkpoint.rs @@ -16,8 +16,8 @@ use crate::listener::IntentEventId; use executor_core::sync_checkpoint_repository::Checkpoint; -use parentchain_primitives::EventId; use parity_scale_codec::{Decode, Encode}; +use primitives::EventId; /// Represents parentchain sync checkpoint. #[derive(Clone, Debug, PartialEq, Encode, Decode)] diff --git a/tee-worker/omni-executor/parentchain/rpc-client/Cargo.toml b/tee-worker/omni-executor/parentchain/rpc-client/Cargo.toml index 27535dca6d..a4ff9e11ae 100644 --- a/tee-worker/omni-executor/parentchain/rpc-client/Cargo.toml +++ b/tee-worker/omni-executor/parentchain/rpc-client/Cargo.toml @@ -11,8 +11,10 @@ parity-scale-codec = { workspace = true, features = ["derive"] } scale-encode = { workspace = true } subxt = { workspace = true } subxt-core = { workspace = true } +tokio = { workspace = true } -parentchain-primitives = { workspace = true } +# Local dependencies +primitives = { workspace = true } [dev-dependencies] env_logger = { workspace = true } diff --git a/tee-worker/omni-executor/parentchain/rpc-client/src/lib.rs b/tee-worker/omni-executor/parentchain/rpc-client/src/lib.rs index bb2151a581..4fc5d9f48b 100644 --- a/tee-worker/omni-executor/parentchain/rpc-client/src/lib.rs +++ b/tee-worker/omni-executor/parentchain/rpc-client/src/lib.rs @@ -13,16 +13,15 @@ // // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . +pub mod metadata; use async_trait::async_trait; use log::{error, info}; -use parentchain_primitives::{BlockEvent, EventId}; use parity_scale_codec::Encode; +use primitives::{BlockEvent, EventId}; use scale_encode::EncodeAsType; use std::marker::PhantomData; use std::ops::Deref; -use std::thread; -use std::time::Duration; use std::vec::Vec; use subxt::backend::legacy::LegacyRpcMethods; use subxt::backend::BlockRef; @@ -32,11 +31,12 @@ use subxt::events::EventsClient; use subxt::storage::StorageClient; use subxt::tx::TxClient; use subxt::{Config, OnlineClient}; -use subxt_core::utils::AccountId32; +pub use subxt_core::utils::AccountId32; +use tokio::time::{sleep, Duration}; // We don't need to construct this at runtime, // so an empty enum is appropriate: -#[derive(EncodeAsType)] +#[derive(EncodeAsType, Clone)] pub enum CustomConfig {} //todo: adjust if needed @@ -73,8 +73,8 @@ pub struct RuntimeVersion { /// For fetching data from Substrate RPC node #[async_trait] pub trait SubstrateRpcClient { - async fn get_last_finalized_header(&mut self) -> Result, ()>; - async fn get_last_finalized_block_num(&mut self) -> Result; + async fn get_last_finalized_header(&self) -> Result, ()>; + async fn get_last_finalized_block_num(&self) -> Result; async fn get_block_events(&mut self, block_num: u64) -> Result, ()>; async fn get_raw_metadata(&mut self, block_num: Option) -> Result, ()>; async fn submit_tx(&mut self, raw_tx: &[u8]) -> Result<(), ()>; @@ -107,13 +107,18 @@ impl SubxtClient { impl> SubstrateRpcClient for SubxtClient { - async fn get_last_finalized_header(&mut self) -> Result, ()> { + async fn get_last_finalized_header(&self) -> Result, ()> { let finalized_header = self.legacy.chain_get_finalized_head().await.map_err(|_| ())?; self.legacy.chain_get_header(Some(finalized_header)).await.map_err(|_| ()) } - async fn get_last_finalized_block_num(&mut self) -> Result { + async fn get_last_finalized_block_num(&self) -> Result { match self.get_last_finalized_header().await { - Ok(Some(header)) => Ok(header.number().into()), + Ok(Some(header)) => { + let block_num = header.number().into(); + // the parachain currently uses u32 for block numbers but subxt uses u64 + let block_num: u32 = block_num.try_into().map_err(|_| ())?; + Ok(block_num) + }, _ => Err(()), } } @@ -205,7 +210,7 @@ impl> } pub struct MockedRpcClient { - block_num: u64, + block_num: u32, _phantom: PhantomData, } @@ -213,10 +218,10 @@ pub struct MockedRpcClient { impl> SubstrateRpcClient for MockedRpcClient { - async fn get_last_finalized_header(&mut self) -> Result, ()> { + async fn get_last_finalized_header(&self) -> Result, ()> { Ok(None) } - async fn get_last_finalized_block_num(&mut self) -> Result { + async fn get_last_finalized_block_num(&self) -> Result { Ok(self.block_num) } @@ -268,6 +273,7 @@ pub trait SubstrateRpcClientFactory< async fn new_client(&self) -> Result; } +#[derive(Clone)] pub struct SubxtClientFactory { url: String, _phantom: PhantomData, @@ -291,7 +297,7 @@ impl> SubxtClientFactory. +use crate::{SubstrateRpcClient, SubstrateRpcClientFactory, SubxtClientFactory}; use async_trait::async_trait; -use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory, SubxtClientFactory}; use parity_scale_codec::Decode; -use subxt::{Config, Metadata}; +use subxt::Config; use subxt_core::utils::AccountId32; +pub use subxt::Metadata; + #[async_trait] pub trait MetadataProvider { async fn get(&self, block_num: Option) -> M; diff --git a/tee-worker/omni-executor/parentchain/signer/Cargo.toml b/tee-worker/omni-executor/parentchain/signer/Cargo.toml new file mode 100644 index 0000000000..926eb75b8f --- /dev/null +++ b/tee-worker/omni-executor/parentchain/signer/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "parentchain-signer" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition.workspace = true + +[dependencies] +log = { workspace = true } +parity-scale-codec = { workspace = true } +subxt-core = { workspace = true } +subxt-signer = { workspace = true } + +# Local dependencies +executor-core = { workspace = true } +executor-crypto = { workspace = true } +parentchain-rpc-client = { workspace = true } + +[dev-dependencies] +env_logger = { workspace = true } + +[lints] +workspace = true diff --git a/tee-worker/omni-executor/parentchain/listener/src/key_store.rs b/tee-worker/omni-executor/parentchain/signer/src/key_store.rs similarity index 97% rename from tee-worker/omni-executor/parentchain/listener/src/key_store.rs rename to tee-worker/omni-executor/parentchain/signer/src/key_store.rs index a52ebec660..9511a8ac0f 100644 --- a/tee-worker/omni-executor/parentchain/listener/src/key_store.rs +++ b/tee-worker/omni-executor/parentchain/signer/src/key_store.rs @@ -15,7 +15,7 @@ // along with Litentry. If not, see . use executor_core::key_store::KeyStore; -use sp_core::{sr25519, Pair}; +use executor_crypto::{sr25519, PairTrait}; use subxt_signer::sr25519::SecretKeyBytes; /// Generates and stores keys used by for communication with parentchain` diff --git a/tee-worker/omni-executor/parentchain/signer/src/lib.rs b/tee-worker/omni-executor/parentchain/signer/src/lib.rs new file mode 100644 index 0000000000..42c1231448 --- /dev/null +++ b/tee-worker/omni-executor/parentchain/signer/src/lib.rs @@ -0,0 +1,27 @@ +pub mod key_store; +mod signer; +pub use signer::TransactionSigner; + +use executor_core::key_store::KeyStore; +use key_store::SubstrateKeyStore; +use log::{error, info}; +use std::sync::Arc; +use subxt_core::utils::AccountId32; +use subxt_signer::sr25519::Keypair; + +pub fn get_signer(key_store: Arc) -> Keypair { + let secret_key_bytes = key_store + .read() + .map_err(|e| { + error!("Could not unseal key: {:?}", e); + }) + .unwrap(); + let signer = subxt_signer::sr25519::Keypair::from_secret_key(secret_key_bytes) + .map_err(|e| { + error!("Could not create secret key: {:?}", e); + }) + .unwrap(); + + info!("Substrate signer address: {}", AccountId32::from(signer.public_key())); + signer +} diff --git a/tee-worker/omni-executor/parentchain/listener/src/transaction_signer.rs b/tee-worker/omni-executor/parentchain/signer/src/signer.rs similarity index 95% rename from tee-worker/omni-executor/parentchain/listener/src/transaction_signer.rs rename to tee-worker/omni-executor/parentchain/signer/src/signer.rs index 10c42729e2..0bdbc64271 100644 --- a/tee-worker/omni-executor/parentchain/listener/src/transaction_signer.rs +++ b/tee-worker/omni-executor/parentchain/signer/src/signer.rs @@ -1,7 +1,9 @@ -use crate::metadata::{MetadataProvider, SubxtMetadataProvider}; use executor_core::key_store::KeyStore; use log::error; -use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use parentchain_rpc_client::{ + metadata::{MetadataProvider, SubxtMetadataProvider}, + SubstrateRpcClient, SubstrateRpcClientFactory, +}; use parity_scale_codec::Decode; use std::marker::PhantomData; use std::sync::Arc; diff --git a/tee-worker/omni-executor/primitives/Cargo.toml b/tee-worker/omni-executor/primitives/Cargo.toml new file mode 100644 index 0000000000..4f76ecc7c4 --- /dev/null +++ b/tee-worker/omni-executor/primitives/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "primitives" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition.workspace = true + +[dependencies] +base64 = { workspace = true } +bitcoin = { workspace = true, features = ["secp-recovery"] } +hex = { workspace = true } +log = { workspace = true } +parity-scale-codec = { workspace = true } +scale-info = { workspace = true } +serde = { workspace = true } + +executor-crypto = { workspace = true } +heima-primitives = { package = "core-primitives", path = "../../../common/primitives/core", default-features = false, features = ["std"] } +sp-core = { workspace = true } + +[lints] +workspace = true diff --git a/tee-worker/omni-executor/parentchain/primitives/src/lib.rs b/tee-worker/omni-executor/primitives/src/lib.rs similarity index 63% rename from tee-worker/omni-executor/parentchain/primitives/src/lib.rs rename to tee-worker/omni-executor/primitives/src/lib.rs index 70534f9918..740d20345b 100644 --- a/tee-worker/omni-executor/parentchain/primitives/src/lib.rs +++ b/tee-worker/omni-executor/primitives/src/lib.rs @@ -14,7 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use executor_core::primitives::GetEventId; +pub mod signature; +pub mod utils; +pub use heima_primitives::{ + omni_account::{MemberAccount, OmniAccountAuthType}, + BlockNumber, Hash, Identity, Nonce, ShardIdentifier, Web2IdentityType, +}; +pub use sp_core::crypto::AccountId32 as AccountId; + +use parity_scale_codec::{Decode, Encode}; +use std::fmt::Debug; + +pub trait GetEventId { + fn get_event_id(&self) -> Id; +} /// Used to uniquely identify intent event on parentchain. #[derive(Clone, Debug)] @@ -54,3 +67,21 @@ impl GetEventId for BlockEvent { self.id.clone() } } + +pub trait TryFromSubxtType: Sized { + fn try_from_subxt_type(t: T) -> Result; +} + +impl TryFromSubxtType for Identity { + fn try_from_subxt_type(t: T) -> Result { + let bytes = t.encode(); + Identity::decode(&mut &bytes[..]).map_err(|_| ()) + } +} + +impl TryFromSubxtType for MemberAccount { + fn try_from_subxt_type(t: T) -> Result { + let bytes = t.encode(); + MemberAccount::decode(&mut &bytes[..]).map_err(|_| ()) + } +} diff --git a/tee-worker/omni-executor/primitives/src/signature/bitcoin.rs b/tee-worker/omni-executor/primitives/src/signature/bitcoin.rs new file mode 100644 index 0000000000..1767b4aae1 --- /dev/null +++ b/tee-worker/omni-executor/primitives/src/signature/bitcoin.rs @@ -0,0 +1,69 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct BitcoinSignature(pub [u8; 65]); + +impl TryFrom<&[u8]> for BitcoinSignature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(BitcoinSignature(inner)) + } else { + Err(()) + } + } +} + +impl Serialize for BitcoinSignature { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self)) + } +} + +impl<'de> Deserialize<'de> for BitcoinSignature { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + BitcoinSignature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +impl AsRef<[u8; 65]> for BitcoinSignature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for BitcoinSignature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} diff --git a/tee-worker/omni-executor/primitives/src/signature/bitcoin_signature.rs b/tee-worker/omni-executor/primitives/src/signature/bitcoin_signature.rs new file mode 100644 index 0000000000..1767b4aae1 --- /dev/null +++ b/tee-worker/omni-executor/primitives/src/signature/bitcoin_signature.rs @@ -0,0 +1,69 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct BitcoinSignature(pub [u8; 65]); + +impl TryFrom<&[u8]> for BitcoinSignature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(BitcoinSignature(inner)) + } else { + Err(()) + } + } +} + +impl Serialize for BitcoinSignature { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self)) + } +} + +impl<'de> Deserialize<'de> for BitcoinSignature { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + BitcoinSignature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +impl AsRef<[u8; 65]> for BitcoinSignature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for BitcoinSignature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} diff --git a/tee-worker/omni-executor/primitives/src/signature/ethereum.rs b/tee-worker/omni-executor/primitives/src/signature/ethereum.rs new file mode 100644 index 0000000000..6815175440 --- /dev/null +++ b/tee-worker/omni-executor/primitives/src/signature/ethereum.rs @@ -0,0 +1,69 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct EthereumSignature(pub [u8; 65]); + +impl TryFrom<&[u8]> for EthereumSignature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(EthereumSignature(inner)) + } else { + Err(()) + } + } +} + +impl Serialize for EthereumSignature { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self)) + } +} + +impl<'de> Deserialize<'de> for EthereumSignature { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + EthereumSignature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +impl AsRef<[u8; 65]> for EthereumSignature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for EthereumSignature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} diff --git a/tee-worker/omni-executor/primitives/src/signature/ethereum_signature.rs b/tee-worker/omni-executor/primitives/src/signature/ethereum_signature.rs new file mode 100644 index 0000000000..6815175440 --- /dev/null +++ b/tee-worker/omni-executor/primitives/src/signature/ethereum_signature.rs @@ -0,0 +1,69 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct EthereumSignature(pub [u8; 65]); + +impl TryFrom<&[u8]> for EthereumSignature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(EthereumSignature(inner)) + } else { + Err(()) + } + } +} + +impl Serialize for EthereumSignature { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self)) + } +} + +impl<'de> Deserialize<'de> for EthereumSignature { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + EthereumSignature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +impl AsRef<[u8; 65]> for EthereumSignature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for EthereumSignature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} diff --git a/tee-worker/omni-executor/primitives/src/signature/heima_multi_signature.rs b/tee-worker/omni-executor/primitives/src/signature/heima_multi_signature.rs new file mode 100644 index 0000000000..932b5891d4 --- /dev/null +++ b/tee-worker/omni-executor/primitives/src/signature/heima_multi_signature.rs @@ -0,0 +1,217 @@ +use crate::signature::{BitcoinSignature, EthereumSignature}; +use bitcoin::sign_message::{signed_msg_hash, MessageSignature}; +use executor_crypto::{ + ecdsa, ed25519, + hashing::{blake2_256, keccak_256}, + secp256k1::{ + secp256k1_ecdsa_recover, secp256k1_ecdsa_recover_compressed, EcdsaVerifyError, Secp256k1, + }, + sr25519, ByteArray, PairTrait, +}; +use heima_primitives::{Address20, Address32, Address33, Identity}; +use log::error; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; + +#[derive( + Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen, Serialize, Deserialize, +)] +pub enum HeimaMultiSignature { + /// An Ed25519 signature. + #[codec(index = 0)] + Ed25519(ed25519::Signature), + /// An Sr25519 signature. + #[codec(index = 1)] + Sr25519(sr25519::Signature), + /// An ECDSA/SECP256k1 signature. + #[codec(index = 2)] + Ecdsa(ecdsa::Signature), + /// An ECDSA/keccak256 signature. An Ethereum signature. hash message with keccak256 + #[codec(index = 3)] + Ethereum(EthereumSignature), + /// Bitcoin signed message, a hex-encoded string of original &[u8] message, without `0x` prefix + #[codec(index = 4)] + Bitcoin(BitcoinSignature), +} + +impl HeimaMultiSignature { + pub fn verify(&self, msg: &[u8], signer: &Identity) -> bool { + match signer { + Identity::Substrate(address) => { + self.verify_substrate(substrate_wrap(msg).as_slice(), address) + || self.verify_substrate(msg, address) + }, + Identity::Evm(address) => self.verify_evm(msg, address), + Identity::Bitcoin(address) => self.verify_bitcoin(msg, address), + Identity::Solana(address) => self.verify_solana(msg, address), + _ => false, + } + } + + fn verify_substrate(&self, msg: &[u8], signer: &Address32) -> bool { + match (self, signer) { + (Self::Ed25519(ref sig), who) => match ed25519::Public::from_slice(who.as_ref()) { + Ok(signer) => ed25519::Pair::verify(sig, msg, &signer), + Err(()) => false, + }, + (Self::Sr25519(ref sig), who) => match sr25519::Public::from_slice(who.as_ref()) { + Ok(signer) => sr25519::Pair::verify(sig, msg, &signer), + Err(()) => false, + }, + (Self::Ecdsa(ref sig), who) => { + let m = blake2_256(msg); + match secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { + Ok(pubkey) => { + &blake2_256(pubkey.as_ref()) == >::as_ref(who) + }, + _ => false, + } + }, + _ => false, + } + } + + fn verify_evm(&self, msg: &[u8], signer: &Address20) -> bool { + match self { + Self::Ethereum(ref sig) => { + return verify_evm_signature(evm_eip191_wrap(msg).as_slice(), sig, signer) + || verify_evm_signature(msg, sig, signer) + }, + _ => false, + } + } + + fn verify_bitcoin(&self, msg: &[u8], signer: &Address33) -> bool { + match self { + Self::Bitcoin(ref sig) => { + verify_bitcoin_signature(hex::encode(msg).as_str(), sig, signer) + || match std::str::from_utf8(msg) { + Err(_) => false, + Ok(prettified) => verify_bitcoin_signature(prettified, sig, signer), + } + }, + _ => false, + } + } + + // https://github.com/solana-labs/solana/blob/master/docs/src/proposals/off-chain-message-signing.md + fn verify_solana(&self, msg: &[u8], signer: &Address32) -> bool { + match (self, signer) { + (Self::Ed25519(ref sig), who) => match ed25519::Public::from_slice(who.as_ref()) { + Ok(signer) => ed25519::Pair::verify(sig, msg, &signer), + Err(()) => false, + }, + _ => false, + } + } +} + +pub fn verify_evm_signature(msg: &[u8], sig: &EthereumSignature, who: &Address20) -> bool { + let digest = keccak_256(msg); + return match recover_evm_address(&digest, sig.as_ref()) { + Ok(recovered_evm_address) => recovered_evm_address == who.as_ref().as_slice(), + Err(_e) => { + error!("Could not verify evm signature msg: {:?}, signer {:?}", msg, who); + false + }, + }; +} + +pub fn verify_bitcoin_signature(msg: &str, sig: &BitcoinSignature, who: &Address33) -> bool { + if let Ok(msg_sig) = MessageSignature::from_slice(sig.as_ref()) { + let msg_hash = signed_msg_hash(msg); + let secp = Secp256k1::new(); + return match msg_sig.recover_pubkey(&secp, msg_hash) { + Ok(recovered_pub_key) => &recovered_pub_key.inner.serialize() == who.as_ref(), + Err(_) => { + error!("Could not recover pubkey from bitcoin msg: {:?}, signer {:?}", msg, who); + false + }, + }; + } + + false +} + +impl From for HeimaMultiSignature { + fn from(x: ed25519::Signature) -> Self { + Self::Ed25519(x) + } +} + +impl From for HeimaMultiSignature { + fn from(x: sr25519::Signature) -> Self { + Self::Sr25519(x) + } +} + +impl From for HeimaMultiSignature { + fn from(x: ecdsa::Signature) -> Self { + Self::Ecdsa(x) + } +} + +pub fn recover_evm_address(msg: &[u8; 32], sig: &[u8; 65]) -> Result<[u8; 20], EcdsaVerifyError> { + let pubkey = secp256k1_ecdsa_recover(sig, msg)?; + let hashed_pk = keccak_256(&pubkey); + + let mut addr = [0u8; 20]; + addr[..20].copy_from_slice(&hashed_pk[12..32]); + Ok(addr) +} + +// see https://github.com/litentry/litentry-parachain/issues/1137 +fn substrate_wrap(msg: &[u8]) -> Vec { + ["".as_bytes(), msg, "".as_bytes()].concat() +} + +// see https://github.com/litentry/litentry-parachain/issues/1970 +fn evm_eip191_wrap(msg: &[u8]) -> Vec { + ["\x19Ethereum Signed Message:\n".as_bytes(), msg.len().to_string().as_bytes(), msg].concat() +} + +#[cfg(test)] +mod tests { + use super::*; + use base64::{engine::general_purpose::STANDARD, Engine}; + + #[test] + fn verify_bitcoin_signature_works() { + // generated by unisat-wallet API: https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet + let msg: Vec = vec![ + 3, 93, 250, 112, 216, 101, 89, 57, 83, 88, 100, 252, 203, 15, 64, 127, 138, 37, 2, 40, + 147, 95, 245, 27, 97, 202, 62, 205, 151, 0, 175, 177, + ]; + let pubkey: Vec = vec![ + 3, 93, 250, 112, 216, 101, 89, 57, 83, 88, 100, 252, 203, 15, 64, 127, 138, 37, 2, 40, + 147, 95, 245, 27, 97, 202, 62, 205, 151, 0, 175, 177, 216, + ]; + let sig: Vec = STANDARD.decode("G2LhyYzWT2o8UoBsuhJsqFgwm3tlE0cW4aseCXKqVuNATk6K/uEHlPzDFmtlMADywDHl5vLCWcNpwmQLD7n/yvc=").unwrap(); + + let pubkey_ref: &[u8] = pubkey.as_ref(); + let sig_ref: &[u8] = sig.as_ref(); + assert!(verify_bitcoin_signature( + hex::encode(msg).as_str(), + &sig_ref.try_into().unwrap(), + &pubkey_ref.try_into().unwrap() + )); + } + + #[test] + fn verify_solana_signature_works() { + let signer = + Identity::from_did("did:litentry:solana:E9SegbpSr21FPLbUhoTNH6C2ja7KDkptybqSaT84wMH6") + .unwrap(); + let signature: [u8; 64] = [ + 62, 25, 148, 186, 53, 137, 248, 174, 149, 187, 225, 24, 186, 48, 24, 109, 100, 27, 149, + 196, 66, 5, 222, 140, 22, 16, 136, 239, 154, 22, 133, 96, 79, 2, 180, 106, 150, 112, + 116, 11, 6, 35, 32, 4, 145, 240, 54, 130, 206, 193, 200, 57, 241, 112, 35, 122, 226, + 97, 174, 231, 221, 13, 98, 2, + ]; + let result = HeimaMultiSignature::Ed25519(ed25519::Signature::from_raw(signature)) + .verify(b"test message", &signer); + assert_eq!(result, true); + } +} diff --git a/tee-worker/omni-executor/primitives/src/signature/mod.rs b/tee-worker/omni-executor/primitives/src/signature/mod.rs new file mode 100644 index 0000000000..3e888d7c64 --- /dev/null +++ b/tee-worker/omni-executor/primitives/src/signature/mod.rs @@ -0,0 +1,8 @@ +mod bitcoin; +pub use bitcoin::BitcoinSignature; + +mod ethereum; +pub use ethereum::EthereumSignature; + +mod heima_multi_signature; +pub use heima_multi_signature::HeimaMultiSignature; diff --git a/tee-worker/omni-executor/primitives/src/utils/hex.rs b/tee-worker/omni-executor/primitives/src/utils/hex.rs new file mode 100644 index 0000000000..725c43ccd4 --- /dev/null +++ b/tee-worker/omni-executor/primitives/src/utils/hex.rs @@ -0,0 +1,119 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use hex::FromHexError; +use parity_scale_codec::{Decode, Encode, Error as CodecError}; +use std::{string::String, vec::Vec}; + +#[derive(Debug)] +pub enum Error { + Hex(FromHexError), + Codec(CodecError), +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Error::Hex(e) => write!(f, "Hex error: {}", e), + Error::Codec(e) => write!(f, "Codec error: {}", e), + } + } +} + +/// Trait to encode a given value to a hex string, prefixed with "0x". +pub trait ToHexPrefixed { + fn to_hex(&self) -> String; +} + +impl ToHexPrefixed for T { + fn to_hex(&self) -> String { + hex_encode(&self.encode()) + } +} + +/// Trait to decode a hex string to a given output. +pub trait FromHexPrefixed { + type Output; + + fn from_hex(msg: &str) -> Result; +} + +impl FromHexPrefixed for T { + type Output = T; + + fn from_hex(msg: &str) -> Result { + let byte_array = decode_hex(msg).map_err(Error::Hex)?; + Decode::decode(&mut byte_array.as_slice()).map_err(Error::Codec) + } +} + +/// Hex encodes given data and preappends a "0x". +pub fn hex_encode(data: &[u8]) -> String { + let mut hex_str = hex::encode(data); + hex_str.insert_str(0, "0x"); + hex_str +} + +/// Helper method for decoding hex. +pub fn decode_hex>(message: T) -> Result, FromHexError> { + let message = message.as_ref(); + let message = match message { + [b'0', b'x', hex_value @ ..] => hex_value, + _ => message, + }; + + let decoded_message = hex::decode(message)?; + Ok(decoded_message) +} + +#[cfg(test)] +mod tests { + use super::*; + use parity_scale_codec::{Decode, Encode}; + use std::string::ToString; + + #[test] + fn hex_encode_decode_works() { + let data = "Hello World!".to_string(); + + let hex_encoded_data = hex_encode(&data.encode()); + let decoded_data = + String::decode(&mut decode_hex(hex_encoded_data).unwrap().as_slice()).unwrap(); + + assert_eq!(data, decoded_data); + } + + #[test] + fn hex_encode_decode_works_empty_input() { + let data = String::new(); + + let hex_encoded_data = hex_encode(&data.encode()); + let decoded_data = + String::decode(&mut decode_hex(hex_encoded_data).unwrap().as_slice()).unwrap(); + + assert_eq!(data, decoded_data); + } + + #[test] + fn to_hex_from_hex_works() { + let data = "Hello World!".to_string(); + + let hex_encoded_data = data.to_hex(); + let decoded_data = String::from_hex(&hex_encoded_data).unwrap(); + + assert_eq!(data, decoded_data); + } +} diff --git a/tee-worker/omni-executor/primitives/src/utils/mod.rs b/tee-worker/omni-executor/primitives/src/utils/mod.rs new file mode 100644 index 0000000000..ce02e677d6 --- /dev/null +++ b/tee-worker/omni-executor/primitives/src/utils/mod.rs @@ -0,0 +1 @@ +pub mod hex; diff --git a/tee-worker/omni-executor/rpc-server/Cargo.toml b/tee-worker/omni-executor/rpc-server/Cargo.toml new file mode 100644 index 0000000000..80ca20b293 --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "rpc-server" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition.workspace = true + +[dependencies] +hex = { workspace = true } +jsonrpsee = { workspace = true } +log = { workspace = true } +parity-scale-codec = { workspace = true } +rand = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } + +# Local dependencies +executor-core = { workspace = true } +executor-crypto = { workspace = true } +executor-storage = { workspace = true } +heima-authentication = { workspace = true } +heima-identity-verification = { workspace = true } +native-task-handler = { workspace = true } +parentchain-rpc-client = { workspace = true } +primitives = { workspace = true } + +[lints] +workspace = true + +[features] +gramine-quote = [] diff --git a/tee-worker/omni-executor/rpc-server/src/authentication.rs b/tee-worker/omni-executor/rpc-server/src/authentication.rs new file mode 100644 index 0000000000..0c390b078a --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/authentication.rs @@ -0,0 +1,183 @@ +use crate::server::RpcContext; +use executor_core::native_call::NativeCall; +use executor_crypto::hashing::blake2_256; +use executor_storage::{MemberOmniAccountStorage, Storage, VerificationCodeStorage}; +use heima_authentication::auth_token::{AuthTokenValidator, Validation}; +use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use parity_scale_codec::{Decode, Encode}; +use primitives::{ + signature::HeimaMultiSignature, + utils::hex::{hex_encode, ToHexPrefixed}, + // AccountId, + Hash, + Identity, + OmniAccountAuthType, + ShardIdentifier, +}; +use std::sync::Arc; +use tokio::runtime::Handle; + +pub type VerificationCode = String; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub enum Authentication { + Web3(HeimaMultiSignature), + Email(VerificationCode), + AuthToken(String), + OAuth2(OAuth2Data), +} + +impl From for OmniAccountAuthType { + fn from(value: Authentication) -> Self { + match value { + Authentication::Web3(_) => OmniAccountAuthType::Web3, + Authentication::Email(_) => OmniAccountAuthType::Email, + Authentication::OAuth2(_) => OmniAccountAuthType::OAuth2, + Authentication::AuthToken(_) => OmniAccountAuthType::AuthToken, + } + } +} + +#[derive(Debug)] +pub enum AuthenticationError { + Web3InvalidSignature, + EmailVerificationCodeNotFound, + EmailInvalidVerificationCode, + // OAuth2Error(String), + #[allow(dead_code)] + AuthTokenError(AuthTokenError), +} + +#[derive(Debug)] +pub enum AuthTokenError { + InvalidToken, + OmniAccountNotFound, + BlockNumberError, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub enum OAuth2Provider { + Google, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct OAuth2Data { + pub provider: OAuth2Provider, + pub code: String, + pub state: String, + pub redirect_uri: String, +} + +pub fn verify_web3_authentication( + signature: &HeimaMultiSignature, + call: &NativeCall, + nonce: u32, + mrenclave: &[u8; 32], + shard: &ShardIdentifier, +) -> Result<(), AuthenticationError> { + let mut payload = call.encode(); + payload.append(&mut nonce.encode()); + payload.append(&mut mrenclave.encode()); + payload.append(&mut shard.encode()); + + // The signature should be valid in either case: + // 1. blake2_256(payload) + // 2. Signature Prefix + blake2_256(payload) + + let hashed = blake2_256(&payload); + + let prettified_msg_hash = call.signature_message_prefix() + &hex_encode(&hashed); + let prettified_msg_hash = prettified_msg_hash.as_bytes(); + + // Most common signatures variants by clients are verified first (4 and 2). + match signature.verify(prettified_msg_hash, call.sender_identity()) + || signature.verify(&hashed, call.sender_identity()) + { + true => Ok(()), + false => Err(AuthenticationError::Web3InvalidSignature), + } +} + +pub fn verify_email_authentication< + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, +>( + ctx: Arc>, + sender_identity: &Identity, + verification_code: &VerificationCode, +) -> Result<(), AuthenticationError> { + let verification_code_storage = VerificationCodeStorage::new(ctx.storage_db.clone()); + let Some(code) = verification_code_storage.get(&sender_identity.hash()) else { + return Err(AuthenticationError::EmailVerificationCodeNotFound); + }; + if code != *verification_code { + return Err(AuthenticationError::EmailInvalidVerificationCode); + } + let _ = verification_code_storage.remove(&sender_identity.hash()); + + Ok(()) +} + +pub fn verify_auth_token_authentication< + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, +>( + ctx: Arc>, + handle: Handle, + sender_identity: &Identity, + auth_token: &str, +) -> Result<(), AuthenticationError> { + let current_block = handle + .block_on(async { + let client = ctx.parentchain_rpc_client_factory.new_client().await.map_err(|e| { + log::error!("Could not create client: {:?}", e); + })?; + client.get_last_finalized_block_num().await.map_err(|e| { + log::error!("Could not get last finalized block number: {:?}", e); + }) + }) + .map_err(|_| AuthenticationError::AuthTokenError(AuthTokenError::BlockNumberError))?; + let member_omni_account_storage = MemberOmniAccountStorage::new(ctx.storage_db.clone()); + let Some(omni_account) = member_omni_account_storage.get(&sender_identity.hash()) else { + return Err(AuthenticationError::AuthTokenError(AuthTokenError::OmniAccountNotFound)); + }; + let validation = Validation::new(omni_account.to_hex(), current_block); + + if auth_token.validate(ctx.jwt_secret.as_bytes(), validation).is_err() { + return Err(AuthenticationError::AuthTokenError(AuthTokenError::InvalidToken)); + } + + Ok(()) +} + +pub fn verify_oauth2_authentication< + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, +>( + _ctx: Arc>, + _sender_identity_hash: Hash, + _payload: &OAuth2Data, +) -> Result<(), AuthenticationError> { + // TODO: get OmniAccount from storage + todo!() + // match payload.provider { + // OAuth2Provider::Google => { + // verify_google_oauth2(ctx, sender_identity_hash, omni_account, payload).await + // }, + // } +} + +// async fn verify_google_oauth2( +// _ctx: Arc, +// _sender_identity_hash: Hash, +// _omni_account: AccountId, +// _payload: &OAuth2Data, +// ) -> Result<(), AuthenticationError> { +// todo!() +// } diff --git a/tee-worker/omni-executor/rpc-server/src/error_code.rs b/tee-worker/omni-executor/rpc-server/src/error_code.rs new file mode 100644 index 0000000000..126f58fccc --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/error_code.rs @@ -0,0 +1,8 @@ +// we should use -32000 to -32099 for implementation defined error codes, +// see https://www.jsonrpc.org/specification#error_object + +pub const INVALID_AES_REQUEST_CODE: i32 = -32000; +pub const INVALID_SHARD_CODE: i32 = -32001; +pub const REQUEST_DECRYPTION_FAILED_CODE: i32 = -32002; +pub const INVALID_AUTHENTICATED_CALL_CODE: i32 = -32003; +pub const AUTHENTICATION_FAILED_CODE: i32 = -32004; diff --git a/tee-worker/omni-executor/rpc-server/src/lib.rs b/tee-worker/omni-executor/rpc-server/src/lib.rs new file mode 100644 index 0000000000..98f1de4b88 --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/lib.rs @@ -0,0 +1,9 @@ +mod authentication; +mod error_code; +mod methods; +mod request; +mod server; +mod shielding_key; + +pub use server::start_server; +pub use shielding_key::ShieldingKey; diff --git a/tee-worker/omni-executor/rpc-server/src/methods/get_shielding_key.rs b/tee-worker/omni-executor/rpc-server/src/methods/get_shielding_key.rs new file mode 100644 index 0000000000..f7a4422b54 --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/methods/get_shielding_key.rs @@ -0,0 +1,85 @@ +use crate::server::RpcContext; +use executor_crypto::rsa::traits::PublicKeyParts; +use jsonrpsee::{ + types::{ErrorCode, ErrorObject}, + RpcModule, +}; +use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use primitives::utils::hex::ToHexPrefixed; +use serde::{Deserialize, Serialize}; +use std::vec::Vec; + +#[derive(Serialize, Deserialize)] +struct Rsa3072PubKey { + n: Vec, + e: Vec, +} + +pub fn register_get_shielding_key< + AccountId: Send + Sync + 'static, + Header: Send + Sync + 'static, + RpcClient: SubstrateRpcClient + Send + Sync + 'static, + RpcClientFactory: SubstrateRpcClientFactory + Send + Sync + 'static, +>( + module: &mut RpcModule>, +) { + module + .register_async_method("native_getShieldingKey", |_params, ctx, _| async move { + let public_key = ctx.shielding_key.public_key(); + let public_key_json = serde_json::to_string(&Rsa3072PubKey { + n: public_key.n().to_bytes_le(), + e: public_key.e().to_bytes_le(), + }) + .map_err(|_| ErrorCode::InternalError)?; + + Ok::(public_key_json.to_hex()) + }) + .expect("Failed to register native_getShieldingKey method"); +} + +#[cfg(test)] +mod test { + use super::*; + use crate::{start_server, ShieldingKey}; + use executor_storage::StorageDB; + use jsonrpsee::core::client::ClientT; + use jsonrpsee::rpc_params; + use jsonrpsee::ws_client::WsClientBuilder; + use native_task_handler::NativeTask; + use parentchain_rpc_client::{CustomConfig, SubxtClientFactory}; + use primitives::utils::hex::FromHexPrefixed; + use std::sync::Arc; + use tokio::sync::mpsc; + + #[tokio::test] + pub async fn get_shielding_key_works() { + let port = "2000"; + let shielding_key = ShieldingKey::new(); + let (sender, _) = mpsc::channel::(1); + let client_factory = SubxtClientFactory::::new("ws://localhost:9944"); + let db = StorageDB::open_default("test_storage_db").unwrap(); + let jwt_secret = "secret".to_string(); + + start_server( + port, + Arc::new(client_factory), + shielding_key.clone(), + Arc::new(sender), + Arc::new(db), + [0u8; 32], + jwt_secret, + ) + .await + .unwrap(); + + let url = format!("ws://127.0.0.1:{}", port); + let client = WsClientBuilder::default().build(&url).await.unwrap(); + let response: String = + client.request("native_getShieldingKey", rpc_params![]).await.unwrap(); + let decoded_json = String::from_hex(&response).unwrap(); + let pubkey: Rsa3072PubKey = serde_json::from_str(&decoded_json).unwrap(); + + assert_eq!(pubkey.n, shielding_key.public_key().n().to_bytes_le()); + assert_eq!(pubkey.e, shielding_key.public_key().e().to_bytes_le()); + } +} diff --git a/tee-worker/omni-executor/rpc-server/src/methods/mod.rs b/tee-worker/omni-executor/rpc-server/src/methods/mod.rs new file mode 100644 index 0000000000..dd308cacf3 --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/methods/mod.rs @@ -0,0 +1,23 @@ +mod get_shielding_key; +mod request_email_verification_code; +mod submit_aes_request; + +use crate::server::RpcContext; +use get_shielding_key::register_get_shielding_key; +use jsonrpsee::RpcModule; +use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use request_email_verification_code::register_request_email_verification_code; +use submit_aes_request::register_submit_aes_request; + +pub fn register_methods< + AccountId: Send + Sync + 'static, + Header: Send + Sync + 'static, + RpcClient: SubstrateRpcClient + Send + Sync + 'static, + RpcClientFactory: SubstrateRpcClientFactory + Send + Sync + 'static, +>( + module: &mut RpcModule>, +) { + register_get_shielding_key(module); + register_submit_aes_request(module); + register_request_email_verification_code(module); +} diff --git a/tee-worker/omni-executor/rpc-server/src/methods/request_email_verification_code.rs b/tee-worker/omni-executor/rpc-server/src/methods/request_email_verification_code.rs new file mode 100644 index 0000000000..edb967f67c --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/methods/request_email_verification_code.rs @@ -0,0 +1,44 @@ +use crate::server::RpcContext; +use executor_storage::{Storage, VerificationCodeStorage}; +use heima_identity_verification::web2::email::{ + generate_verification_code, send_verification_email, +}; +use jsonrpsee::{ + types::{ErrorCode, ErrorObject}, + RpcModule, +}; +use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use primitives::{Identity, Web2IdentityType}; + +pub fn register_request_email_verification_code< + AccountId: Send + Sync + 'static, + Header: Send + Sync + 'static, + RpcClient: SubstrateRpcClient + Send + Sync + 'static, + RpcClientFactory: SubstrateRpcClientFactory + Send + Sync + 'static, +>( + module: &mut RpcModule>, +) { + module + .register_async_method("omni_requestEmailVerificationCode", |params, ctx, _| async move { + let Ok(email) = params.one::() else { + return Err(ErrorCode::ParseError.into()); + }; + let email_identity = Identity::from_web2_account(&email, Web2IdentityType::Email); + let verification_code_storage = VerificationCodeStorage::new(ctx.storage_db.clone()); + let verification_code = generate_verification_code(); + + verification_code_storage + .insert(email_identity.hash(), verification_code.clone()) + .map_err(|_| ErrorCode::InternalError)?; + + send_verification_email(&ctx.mailer, email, verification_code) + .await + .map_err(|_| { + log::error!("Failed to send verification email"); + ErrorCode::InternalError + })?; + + Ok::<(), ErrorObject>(()) + }) + .expect("Failed to register omni_requestEmailVerificationCode method"); +} diff --git a/tee-worker/omni-executor/rpc-server/src/methods/submit_aes_request.rs b/tee-worker/omni-executor/rpc-server/src/methods/submit_aes_request.rs new file mode 100644 index 0000000000..08c284d889 --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/methods/submit_aes_request.rs @@ -0,0 +1,131 @@ +use crate::{ + authentication::{ + verify_auth_token_authentication, verify_email_authentication, + verify_oauth2_authentication, verify_web3_authentication, Authentication, + }, + error_code::*, + request::{AesRequest, DecryptableRequest}, + server::RpcContext, +}; +use executor_core::native_call::NativeCall; +use jsonrpsee::{ + types::{ErrorCode, ErrorObject}, + RpcModule, +}; +use native_task_handler::NativeTask; +use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use parity_scale_codec::{Decode, Encode}; +use primitives::{ + utils::hex::{FromHexPrefixed, ToHexPrefixed}, + Nonce, OmniAccountAuthType, +}; +use std::{fmt::Debug, sync::Arc}; +use tokio::{runtime::Handle, sync::oneshot, task}; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct AuthenticatedCall { + pub call: NativeCall, + pub nonce: Nonce, + pub authentication: Authentication, +} + +pub fn register_submit_aes_request< + AccountId: Send + Sync + 'static, + Header: Send + Sync + 'static, + RpcClient: SubstrateRpcClient + Send + Sync + 'static, + RpcClientFactory: SubstrateRpcClientFactory + Send + Sync + 'static, +>( + module: &mut RpcModule>, +) { + module + .register_async_method("native_submitAesRequest", |params, ctx, _| async move { + let Ok(hex_request) = params.one::() else { + return Err(ErrorCode::ParseError.into()); + }; + let Ok(request) = AesRequest::from_hex(&hex_request) else { + return Err(ErrorCode::ServerError(INVALID_AES_REQUEST_CODE).into()); + }; + let context = ctx.clone(); + let aes_request = request.clone(); + let handle = Handle::current(); + let join_handle = + task::spawn_blocking(|| handle_aes_request(aes_request, context, handle)); + let (native_call, auth_type) = join_handle.await.map_err(|e| { + log::error!("Failed to handle AES request: {:?}", e); + ErrorCode::InternalError + })??; + let (response_sender, response_receiver) = oneshot::channel(); + let native_task = NativeTask { call: native_call, auth_type, response_sender }; + + if ctx.native_task_sender.send(native_task).await.is_err() { + log::error!("Failed to send request to native call executor"); + return Err(ErrorCode::InternalError.into()); + } + match response_receiver.await { + Ok(response) => Ok::(response.to_hex()), + Err(e) => { + log::error!("Failed to receive response from native call executor: {:?}", e); + Err(ErrorCode::InternalError.into()) + }, + } + }) + .expect("Failed to register native_submitAesRequest method"); +} + +fn handle_aes_request< + 'a, + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, +>( + mut request: AesRequest, + ctx: Arc>, + handle: Handle, +) -> Result<(NativeCall, OmniAccountAuthType), ErrorObject<'a>> { + if request.shard().encode() != ctx.mrenclave.encode() { + return Err(ErrorCode::ServerError(INVALID_SHARD_CODE).into()); + } + let Ok(encoded_auth_call) = request.decrypt(Box::new(ctx.shielding_key.clone())) else { + return Err(ErrorCode::ServerError(REQUEST_DECRYPTION_FAILED_CODE).into()); + }; + let authenticated_call: AuthenticatedCall = + match AuthenticatedCall::decode(&mut encoded_auth_call.as_slice()) { + Ok(auth_call) => auth_call, + Err(e) => { + log::error!("Failed to decode authenticated call: {:?}", e); + return Err(ErrorCode::ServerError(INVALID_AUTHENTICATED_CALL_CODE).into()); + }, + }; + let authentication_result = match authenticated_call.authentication { + Authentication::Web3(ref signature) => verify_web3_authentication( + signature, + &authenticated_call.call, + authenticated_call.nonce, + &ctx.mrenclave, + &request.shard, + ), + Authentication::Email(ref verification_code) => verify_email_authentication( + ctx, + authenticated_call.call.sender_identity(), + verification_code, + ), + Authentication::OAuth2(ref oauth2_data) => verify_oauth2_authentication( + ctx, + authenticated_call.call.sender_identity().hash(), + oauth2_data, + ), + Authentication::AuthToken(ref auth_token) => verify_auth_token_authentication( + ctx, + handle, + authenticated_call.call.sender_identity(), + auth_token, + ), + }; + + if authentication_result.is_err() { + return Err(ErrorCode::ServerError(AUTHENTICATION_FAILED_CODE).into()); + } + + Ok((authenticated_call.call, authenticated_call.authentication.into())) +} diff --git a/tee-worker/omni-executor/rpc-server/src/request.rs b/tee-worker/omni-executor/rpc-server/src/request.rs new file mode 100644 index 0000000000..f79c87e6bf --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/request.rs @@ -0,0 +1,72 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use executor_crypto::{ + aes256::{aes_decrypt, Aes256Key as RequestAesKey, AesOutput}, + traits::Decrypt, +}; +use parity_scale_codec::{Decode, Encode}; +use primitives::ShardIdentifier; +use std::fmt::Debug; + +// Represent a request that can be decrypted by the enclave +pub trait DecryptableRequest { + type Error; + // the shard getter + fn shard(&self) -> ShardIdentifier; + // how to decrypt the payload + fn decrypt( + &mut self, + shielding_key: Box>, + ) -> Result, Self::Error>; +} + +#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)] +pub struct AesRequest { + pub shard: ShardIdentifier, + pub key: Vec, + pub payload: AesOutput, +} + +impl DecryptableRequest for AesRequest { + type Error = (); + + fn shard(&self) -> ShardIdentifier { + self.shard + } + + fn decrypt( + &mut self, + enclave_shielding_key: Box>, + ) -> core::result::Result, ()> { + let aes_key: RequestAesKey = self.decrypt_aes_key(enclave_shielding_key)?; + aes_decrypt(&aes_key, &mut self.payload).ok_or(()) + } +} + +impl AesRequest { + #[allow(clippy::result_unit_err)] + pub fn decrypt_aes_key( + &mut self, + enclave_shielding_key: Box>, + ) -> core::result::Result { + enclave_shielding_key + .decrypt(&self.key) + .map_err(|_| ())? + .try_into() + .map_err(|_| ()) + } +} diff --git a/tee-worker/omni-executor/rpc-server/src/server.rs b/tee-worker/omni-executor/rpc-server/src/server.rs new file mode 100644 index 0000000000..647b980198 --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/server.rs @@ -0,0 +1,98 @@ +use crate::{methods::register_methods, ShieldingKey}; +use executor_storage::StorageDB; +use heima_identity_verification::web2::email::Mailer; +use jsonrpsee::{server::Server, RpcModule}; +use native_task_handler::NativeTaskSender; +use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use std::{env, marker::PhantomData, net::SocketAddr, sync::Arc}; + +pub(crate) struct RpcContext< + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, +> { + pub shielding_key: ShieldingKey, + pub native_task_sender: Arc, + pub parentchain_rpc_client_factory: Arc, + pub storage_db: Arc, + pub mrenclave: [u8; 32], + pub mailer: Mailer, + pub jwt_secret: String, + phantom_account_id: PhantomData, + phantom_header: PhantomData
, + phantom_rpc_client: PhantomData, +} + +impl< + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, + > RpcContext +{ + pub fn new( + shielding_key: ShieldingKey, + native_task_sender: Arc, + parentchain_rpc_client_factory: Arc, + storage_db: Arc, + mrenclave: [u8; 32], + mailer: Mailer, + jwt_secret: String, + ) -> Self { + Self { + shielding_key, + native_task_sender, + parentchain_rpc_client_factory, + storage_db, + mrenclave, + mailer, + jwt_secret, + phantom_account_id: PhantomData, + phantom_header: PhantomData, + phantom_rpc_client: PhantomData, + } + } +} + +pub async fn start_server< + AccountId: Send + Sync + 'static, + Header: Send + Sync + 'static, + RpcClient: SubstrateRpcClient + Send + Sync + 'static, + RpcClientFactory: SubstrateRpcClientFactory + Send + Sync + 'static, +>( + port: &str, + parentchain_rpc_client_factory: Arc, + shielding_key: ShieldingKey, + native_task_sender: Arc, + storage_db: Arc, + mrenclave: [u8; 32], + jwt_secret: String, +) -> Result<(), Box> { + let address = format!("0.0.0.0:{}", port); + let server = Server::builder().build(address.parse::()?).await?; + + // TODO: move to config + let mailer_api_key = env::var("SENDGRID_API_KEY").unwrap_or("".to_string()); + let mailer_from_email = env::var("SENDGRID_FROM_EMAIL").unwrap_or("".to_string()); + let mailer_from_name = env::var("SENDGRID_FROM_NAME").unwrap_or("".to_string()); + let mailer = Mailer::new(mailer_api_key, mailer_from_email, mailer_from_name); + + let ctx = RpcContext::new( + shielding_key, + native_task_sender, + parentchain_rpc_client_factory, + storage_db, + mrenclave, + mailer, + jwt_secret, + ); + let mut module = RpcModule::new(ctx); + register_methods(&mut module); + + let handle = server.start(module); + log::info!("Server listening on port {}", port); + tokio::spawn(handle.stopped()); + + Ok(()) +} diff --git a/tee-worker/omni-executor/rpc-server/src/shielding_key.rs b/tee-worker/omni-executor/rpc-server/src/shielding_key.rs new file mode 100644 index 0000000000..58bb9d747e --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/shielding_key.rs @@ -0,0 +1,39 @@ +use executor_crypto::{ + rsa::{errors::Error as RsaError, sha2::Sha256, Oaep, RsaPrivateKey, RsaPublicKey}, + traits::Decrypt, +}; + +#[derive(Debug, Clone)] +pub struct ShieldingKey { + key: RsaPrivateKey, +} + +impl ShieldingKey { + pub fn new() -> Self { + Self::default() + } + + pub fn public_key(&self) -> RsaPublicKey { + self.key.to_public_key() + } + + pub fn private_key(&self) -> &RsaPrivateKey { + &self.key + } +} + +impl Decrypt for ShieldingKey { + type Error = RsaError; + + fn decrypt(&self, data: &[u8]) -> Result, Self::Error> { + self.private_key().decrypt(Oaep::new::(), data) + } +} + +impl Default for ShieldingKey { + fn default() -> Self { + let mut rng = rand::thread_rng(); + let key = RsaPrivateKey::new(&mut rng, 3072).expect("Failed to generate RSA key"); + Self { key } + } +}