diff --git a/Cargo.lock b/Cargo.lock index 38063e8060835..a35dbba7d089e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,6 +112,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "698b65a961a9d730fb45b6b0327e20207810c9f61ee421b082b27ba003f49e2b" +[[package]] +name = "array-bytes" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a913633b0c922e6b745072795f50d90ebea78ba31a57e2ac8c2fc7b50950949" + [[package]] name = "arrayref" version = "0.3.6" @@ -343,9 +349,9 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-trait" -version = "0.1.51" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ "proc-macro2", "quote", @@ -427,6 +433,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bdca834647821e0b13d9539a8634eb62d3501b6b6c2cec1722786ee6671b851" + [[package]] name = "beef" version = "0.5.1" @@ -440,15 +452,15 @@ dependencies = [ name = "beefy-gadget" version = "4.0.0-dev" dependencies = [ + "array-bytes", "async-trait", "beefy-primitives", "fnv", "futures", "futures-timer", - "hex", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -456,6 +468,7 @@ dependencies = [ "sc-finality-grandpa", "sc-keystore", "sc-network", + "sc-network-common", "sc-network-gossip", "sc-network-test", "sc-utils", @@ -491,7 +504,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-rpc", "sc-utils", "serde", @@ -507,21 +520,19 @@ dependencies = [ name = "beefy-merkle-tree" version = "4.0.0-dev" dependencies = [ + "array-bytes", "beefy-primitives", "env_logger", - "hex", - "hex-literal", "log", "sp-api", - "tiny-keccak", + "sp-runtime", ] [[package]] name = "beefy-primitives" version = "4.0.0-dev" dependencies = [ - "hex", - "hex-literal", + "array-bytes", "parity-scale-codec", "scale-info", "sp-api", @@ -587,9 +598,9 @@ dependencies = [ [[package]] name = "blake2" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94ba84325db59637ffc528bbe8c7f86c02c57cff5c0e2b9b00f9a851f42f309" +checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" dependencies = [ "digest 0.10.3", ] @@ -852,6 +863,15 @@ dependencies = [ "nom", ] +[[package]] +name = "cfg-expr" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" +dependencies = [ + "smallvec", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -864,6 +884,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chacha20" version = "0.8.1" @@ -896,7 +922,7 @@ dependencies = [ "ansi_term", "clap 3.1.18", "node-cli", - "rand 0.8.4", + "rand 0.8.5", "sc-chain-spec", "sc-keystore", "sp-core", @@ -918,9 +944,9 @@ dependencies = [ [[package]] name = "cid" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a52cffa791ce5cf490ac3b2d6df970dc04f931b04e727be3c3e220e17164dfc4" +checksum = "f6ed9c8b2d17acb8110c46f1da5bf4a696d745e1474a16db0cd2b49cd0249bf2" dependencies = [ "core2", "multibase", @@ -1128,11 +1154,11 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899dc8d22f7771e7f887fb8bafa0c0d3ac1dea0c7f2c0ded6e20a855a7a1e890" +checksum = "b27bbd3e6c422cf6282b047bcdd51ecd9ca9f3497a3be0132ffa08e509b824b0" dependencies = [ - "cranelift-entity 0.85.0", + "cranelift-entity 0.88.0", ] [[package]] @@ -1154,14 +1180,16 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dbdc03f695cf67e7bc45da57155528274f47390b85060af8107eb304ef167c4" +checksum = "872f5d4557a411b087bd731df6347c142ae1004e6467a144a7e33662e5715a01" dependencies = [ - "cranelift-bforest 0.85.0", - "cranelift-codegen-meta 0.85.0", - "cranelift-codegen-shared 0.85.0", - "cranelift-entity 0.85.0", + "arrayvec 0.7.2", + "bumpalo", + "cranelift-bforest 0.88.0", + "cranelift-codegen-meta 0.88.0", + "cranelift-codegen-shared 0.88.0", + "cranelift-entity 0.88.0", "cranelift-isle", "gimli 0.26.1", "log", @@ -1182,11 +1210,11 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea66cbba3eb7fcb3ec9f42839a6d381bd40cf97780397e7167daf9725d4ffa0" +checksum = "21b49fdebb29c62c1fc4da1eeebd609e9d530ecde24a9876def546275f73a244" dependencies = [ - "cranelift-codegen-shared 0.85.0", + "cranelift-codegen-shared 0.88.0", ] [[package]] @@ -1197,9 +1225,9 @@ checksum = "9dabb5fe66e04d4652e434195b45ae65b5c8172d520247b8f66d8df42b2b45dc" [[package]] name = "cranelift-codegen-shared" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712fbebd119a476f59122b4ba51fdce893a66309b5c92bd5506bfb11a0587496" +checksum = "5fc0c091e2db055d4d7f6b7cec2d2ead286bcfaea3357c6a52c2a2613a8cb5ac" [[package]] name = "cranelift-entity" @@ -1209,9 +1237,9 @@ checksum = "3329733e4d4b8e91c809efcaa4faee80bf66f20164e3dd16d707346bd3494799" [[package]] name = "cranelift-entity" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cb8b95859c4e14c9e860db78d596a904fdbe9261990233b62bd526346cb56cb" +checksum = "354a9597be87996c9b278655e68b8447f65dd907256855ad773864edee8d985c" dependencies = [ "serde", ] @@ -1230,11 +1258,11 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7b91b19a7d1221a73f190c0e865c12be77a84f661cac89abfd4ab5820142886" +checksum = "0cd8dd3fb8b82c772f4172e87ae1677b971676fffa7c4e3398e3047e650a266b" dependencies = [ - "cranelift-codegen 0.85.0", + "cranelift-codegen 0.88.0", "log", "smallvec", "target-lexicon", @@ -1242,34 +1270,34 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d4f53bc86fb458e59c695c6a95ce8346e6a8377ee7ffc058e3ac08b5f94cb1" +checksum = "b82527802b1f7d8da288adc28f1dc97ea52943f5871c041213f7b5035ac698a7" [[package]] name = "cranelift-native" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592f035d0ed41214dfeeb37abd536233536a27be6b4c2d39f380cd402f0cff4f" +checksum = "c30ba8b910f1be023af0c39109cb28a8809734942a6b3eecbf2de8993052ea5e" dependencies = [ - "cranelift-codegen 0.85.0", + "cranelift-codegen 0.88.0", "libc", "target-lexicon", ] [[package]] name = "cranelift-wasm" -version = "0.85.0" +version = "0.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295add6bf0b527a8bc50d02e31ff878585d2d2db53cb7e8754d6d82b84480086" +checksum = "776a8916d201894aca9637a20814f1e11abc62acd5cfbe0b4eb2e63922756971" dependencies = [ - "cranelift-codegen 0.85.0", - "cranelift-entity 0.85.0", - "cranelift-frontend 0.85.0", + "cranelift-codegen 0.88.0", + "cranelift-entity 0.88.0", + "cranelift-frontend 0.88.0", "itertools", "log", "smallvec", - "wasmparser 0.85.0", + "wasmparser 0.89.1", "wasmtime-types", ] @@ -1788,6 +1816,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-zebra" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" +dependencies = [ + "curve25519-dalek 3.0.2", + "hex", + "rand_core 0.6.2", + "sha2 0.9.8", + "thiserror", + "zeroize", +] + [[package]] name = "either" version = "1.6.1" @@ -2014,8 +2056,8 @@ dependencies = [ "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.0", - "rand 0.8.4", + "parking_lot 0.12.1", + "rand 0.8.5", "scale-info", ] @@ -2026,7 +2068,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand 0.8.4", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -2077,17 +2119,19 @@ dependencies = [ name = "frame-benchmarking" version = "4.0.0-dev" dependencies = [ + "array-bytes", "frame-support", "frame-system", - "hex-literal", "linregress", "log", "parity-scale-codec", "paste 1.0.6", + "rusty-fork", "scale-info", "serde", "sp-api", "sp-application-crypto", + "sp-core", "sp-io", "sp-keystore", "sp-runtime", @@ -2101,6 +2145,7 @@ name = "frame-benchmarking-cli" version = "4.0.0-dev" dependencies = [ "Inflector", + "array-bytes", "chrono", "clap 3.1.18", "comfy-table", @@ -2110,7 +2155,6 @@ dependencies = [ "gethostname", "handlebars", "hash-db", - "hex", "itertools", "kvdb", "lazy_static", @@ -2118,7 +2162,7 @@ dependencies = [ "log", "memory-db", "parity-scale-codec", - "rand 0.8.4", + "rand 0.8.5", "rand_pcg 0.3.1", "sc-block-builder", "sc-cli", @@ -2190,7 +2234,7 @@ dependencies = [ "frame-support", "honggfuzz", "parity-scale-codec", - "rand 0.8.4", + "rand 0.8.5", "scale-info", "sp-arithmetic", "sp-npos-elections", @@ -2201,9 +2245,10 @@ dependencies = [ name = "frame-executive" version = "4.0.0-dev" dependencies = [ + "array-bytes", "frame-support", "frame-system", - "hex-literal", + "frame-try-runtime", "pallet-balances", "pallet-transaction-payment", "parity-scale-codec", @@ -2250,6 +2295,7 @@ dependencies = [ "serde", "serde_json", "smallvec", + "sp-api", "sp-arithmetic", "sp-core", "sp-core-hashing-proc-macro", @@ -2260,6 +2306,7 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-tracing", + "sp-weights", "tt-call", ] @@ -2268,7 +2315,9 @@ name = "frame-support-procedural" version = "4.0.0-dev" dependencies = [ "Inflector", + "cfg-expr", "frame-support-procedural-tools", + "itertools", "proc-macro2", "quote", "syn", @@ -2355,6 +2404,7 @@ dependencies = [ "sp-runtime", "sp-std", "sp-version", + "sp-weights", "substrate-test-runtime-client", ] @@ -2386,6 +2436,7 @@ name = "frame-try-runtime" version = "0.10.0-dev" dependencies = [ "frame-support", + "parity-scale-codec", "sp-api", "sp-runtime", "sp-std", @@ -2782,9 +2833,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] @@ -2810,12 +2861,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - [[package]] name = "hex_fmt" version = "0.3.0" @@ -3057,12 +3102,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "io-lifetimes" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec58677acfea8a15352d42fc87d11d63596ade9239e0a7c9352914417515dbe6" - [[package]] name = "io-lifetimes" version = "0.7.2" @@ -3187,8 +3226,8 @@ dependencies = [ "hyper", "jsonrpsee-types", "lazy_static", - "parking_lot 0.12.0", - "rand 0.8.4", + "parking_lot 0.12.1", + "rand 0.8.5", "rustc-hash", "serde", "serde_json", @@ -3317,7 +3356,6 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", "log", "node-primitives", "pallet-alliance", @@ -3333,12 +3371,13 @@ dependencies = [ "pallet-collective", "pallet-contracts", "pallet-contracts-primitives", - "pallet-contracts-rpc-runtime-api", + "pallet-contracts-runtime-api", "pallet-conviction-voting", "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", + "pallet-fast-unstake", "pallet-gilt", "pallet-grandpa", "pallet-identity", @@ -3426,7 +3465,7 @@ checksum = "ece7e668abd21387aeb6628130a6f4c802787f014fa46bc83221448322250357" dependencies = [ "kvdb", "parity-util-mem", - "parking_lot 0.12.0", + "parking_lot 0.12.1", ] [[package]] @@ -3441,7 +3480,7 @@ dependencies = [ "num_cpus", "owning_ref", "parity-util-mem", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "regex", "rocksdb", "smallvec", @@ -3547,7 +3586,7 @@ dependencies = [ "libp2p-websocket", "libp2p-yamux", "multiaddr", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project", "rand 0.7.3", "smallvec", @@ -3567,9 +3606,9 @@ dependencies = [ "libp2p-request-response", "libp2p-swarm", "log", - "prost", - "prost-build", - "rand 0.8.4", + "prost 0.10.3", + "prost-build 0.10.4", + "rand 0.8.5", ] [[package]] @@ -3592,11 +3631,11 @@ dependencies = [ "multiaddr", "multihash", "multistream-select", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project", - "prost", - "prost-build", - "rand 0.8.4", + "prost 0.10.3", + "prost-build 0.10.4", + "rand 0.8.5", "ring", "rw-stream-sink", "sha2 0.10.2", @@ -3628,7 +3667,7 @@ dependencies = [ "futures", "libp2p-core", "log", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "smallvec", "trust-dns-resolver", ] @@ -3645,8 +3684,8 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "prost", - "prost-build", + "prost 0.10.3", + "prost-build 0.10.4", "rand 0.7.3", "smallvec", ] @@ -3669,8 +3708,8 @@ dependencies = [ "libp2p-swarm", "log", "prometheus-client", - "prost", - "prost-build", + "prost 0.10.3", + "prost-build 0.10.4", "rand 0.7.3", "regex", "sha2 0.10.2", @@ -3692,8 +3731,8 @@ dependencies = [ "libp2p-swarm", "log", "lru", - "prost", - "prost-build", + "prost 0.10.3", + "prost-build 0.10.4", "prost-codec", "smallvec", "thiserror", @@ -3717,8 +3756,8 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "prost", - "prost-build", + "prost 0.10.3", + "prost-build 0.10.4", "rand 0.7.3", "sha2 0.10.2", "smallvec", @@ -3743,7 +3782,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "rand 0.8.4", + "rand 0.8.5", "smallvec", "socket2", "void", @@ -3777,7 +3816,7 @@ dependencies = [ "libp2p-core", "log", "nohash-hasher", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", "smallvec", "unsigned-varint", @@ -3795,9 +3834,9 @@ dependencies = [ "lazy_static", "libp2p-core", "log", - "prost", - "prost-build", - "rand 0.8.4", + "prost 0.10.3", + "prost-build 0.10.4", + "rand 0.8.5", "sha2 0.10.2", "snow", "static_assertions", @@ -3832,8 +3871,8 @@ dependencies = [ "futures", "libp2p-core", "log", - "prost", - "prost-build", + "prost 0.10.3", + "prost-build 0.10.4", "unsigned-varint", "void", ] @@ -3868,10 +3907,10 @@ dependencies = [ "libp2p-swarm", "log", "pin-project", - "prost", - "prost-build", + "prost 0.10.3", + "prost-build 0.10.4", "prost-codec", - "rand 0.8.4", + "rand 0.8.5", "smallvec", "static_assertions", "thiserror", @@ -3892,9 +3931,9 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "prost", - "prost-build", - "rand 0.8.4", + "prost 0.10.3", + "prost-build 0.10.4", + "rand 0.8.5", "sha2 0.10.2", "thiserror", "unsigned-varint", @@ -4003,7 +4042,7 @@ dependencies = [ "futures-rustls", "libp2p-core", "log", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "quicksink", "rw-stream-sink", "soketto", @@ -4019,7 +4058,7 @@ checksum = "c6dea686217a06072033dc025631932810e2f6ad784e4fafa42e27d311c7a81c" dependencies = [ "futures", "libp2p-core", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "thiserror", "yamux", ] @@ -4052,7 +4091,7 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand 0.8.4", + "rand 0.8.5", "serde", "sha2 0.9.8", "typenum", @@ -4124,12 +4163,6 @@ dependencies = [ "statrs", ] -[[package]] -name = "linux-raw-sys" -version = "0.0.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5284f00d480e1c39af34e72f8ad60b94f47007e3481cd3b731c1d67190ddc7b7" - [[package]] name = "linux-raw-sys" version = "0.0.46" @@ -4285,11 +4318,11 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memfd" -version = "0.4.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6627dc657574b49d6ad27105ed671822be56e0d2547d413bfbf3e8d8fa92e7a" +checksum = "480b5a5de855d11ff13195950bdc8b98b5e942ef47afc447f6615cdcc4e15d80" dependencies = [ - "libc", + "rustix", ] [[package]] @@ -4336,15 +4369,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6566c70c1016f525ced45d7b7f97730a2bafb037c788211d0c186ef5b2189f0a" dependencies = [ "hash-db", - "hashbrown 0.12.0", + "hashbrown 0.12.3", "parity-util-mem", ] [[package]] name = "memory_units" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" [[package]] name = "merlin" @@ -4484,7 +4517,7 @@ dependencies = [ "num-complex", "num-rational 0.4.0", "num-traits", - "rand 0.8.4", + "rand 0.8.5", "rand_distr", "simba", "typenum", @@ -4507,7 +4540,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d66043b25d4a6cccb23619d10c19c25304b355a7dccd4a8e11423dd2382146" dependencies = [ - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -4605,12 +4638,12 @@ dependencies = [ name = "node-bench" version = "0.9.0-dev" dependencies = [ + "array-bytes", "clap 3.1.18", "derive_more", "fs_extra", "futures", "hash-db", - "hex", "kitchensink-runtime", "kvdb", "kvdb-rocksdb", @@ -4642,6 +4675,7 @@ dependencies = [ name = "node-cli" version = "3.0.0-dev" dependencies = [ + "array-bytes", "assert_cmd", "async-std", "clap 3.1.18", @@ -4651,7 +4685,6 @@ dependencies = [ "frame-system", "frame-system-rpc-runtime-api", "futures", - "hex-literal", "jsonrpsee", "kitchensink-runtime", "log", @@ -4667,7 +4700,7 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "platforms", - "rand 0.8.4", + "rand 0.8.5", "regex", "remote-externalities", "sc-authority-discovery", @@ -4792,7 +4825,6 @@ version = "3.0.0-dev" dependencies = [ "jsonrpsee", "node-primitives", - "pallet-contracts-rpc", "pallet-mmr-rpc", "pallet-transaction-payment-rpc", "sc-chain-spec", @@ -4804,6 +4836,7 @@ dependencies = [ "sc-finality-grandpa-rpc", "sc-rpc", "sc-rpc-api", + "sc-rpc-spec-v2", "sc-sync-state-rpc", "sc-transaction-pool-api", "sp-api", @@ -4879,7 +4912,6 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", "pallet-aura", "pallet-balances", "pallet-grandpa", @@ -4973,6 +5005,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-complex" version = "0.4.0" @@ -5009,7 +5052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ "autocfg", - "num-bigint", + "num-bigint 0.2.6", "num-integer", "num-traits", ] @@ -5021,15 +5064,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" dependencies = [ "autocfg", + "num-bigint 0.4.3", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", "libm", @@ -5066,6 +5110,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +dependencies = [ + "crc32fast", + "hashbrown 0.12.3", + "indexmap", + "memchr", +] + [[package]] name = "once_cell" version = "1.12.0" @@ -5124,11 +5180,10 @@ dependencies = [ name = "pallet-alliance" version = "4.0.0-dev" dependencies = [ + "array-bytes", "frame-benchmarking", "frame-support", "frame-system", - "hex", - "hex-literal", "log", "pallet-balances", "pallet-collective", @@ -5299,7 +5354,7 @@ dependencies = [ "frame-election-provider-support", "honggfuzz", "pallet-bags-list", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -5359,12 +5414,11 @@ dependencies = [ name = "pallet-beefy-mmr" version = "4.0.0-dev" dependencies = [ + "array-bytes", "beefy-merkle-tree", "beefy-primitives", "frame-support", "frame-system", - "hex", - "hex-literal", "log", "pallet-beefy", "pallet-mmr", @@ -5436,13 +5490,13 @@ dependencies = [ name = "pallet-contracts" version = "4.0.0-dev" dependencies = [ + "array-bytes", "assert_matches", "bitflags", "env_logger", "frame-benchmarking", "frame-support", "frame-system", - "hex-literal", "impl-trait-for-tuples", "log", "pallet-balances", @@ -5453,7 +5507,7 @@ dependencies = [ "pallet-utility", "parity-scale-codec", "pretty_assertions", - "rand 0.8.4", + "rand 0.8.5", "rand_pcg 0.3.1", "scale-info", "serde", @@ -5475,10 +5529,6 @@ version = "6.0.0" dependencies = [ "bitflags", "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-rpc", "sp-runtime", "sp-std", ] @@ -5493,24 +5543,7 @@ dependencies = [ ] [[package]] -name = "pallet-contracts-rpc" -version = "4.0.0-dev" -dependencies = [ - "jsonrpsee", - "pallet-contracts-primitives", - "pallet-contracts-rpc-runtime-api", - "parity-scale-codec", - "serde", - "serde_json", - "sp-api", - "sp-blockchain", - "sp-core", - "sp-rpc", - "sp-runtime", -] - -[[package]] -name = "pallet-contracts-rpc-runtime-api" +name = "pallet-contracts-runtime-api" version = "4.0.0-dev" dependencies = [ "pallet-contracts-primitives", @@ -5570,7 +5603,7 @@ dependencies = [ "pallet-balances", "pallet-election-provider-support-benchmarking", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", "scale-info", "sp-arithmetic", @@ -5665,6 +5698,30 @@ dependencies = [ "sp-tasks", ] +[[package]] +name = "pallet-fast-unstake" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", + "sp-tracing", + "substrate-test-utils", +] + [[package]] name = "pallet-gilt" version = "4.0.0-dev" @@ -5803,12 +5860,12 @@ dependencies = [ name = "pallet-mmr" version = "4.0.0-dev" dependencies = [ + "array-bytes", "ckb-merkle-mountain-range", "env_logger", "frame-benchmarking", "frame-support", "frame-system", - "hex-literal", "itertools", "parity-scale-codec", "scale-info", @@ -5889,6 +5946,7 @@ dependencies = [ "log", "pallet-balances", "parity-scale-codec", + "rand 0.8.5", "scale-info", "sp-core", "sp-io", @@ -5917,6 +5975,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", + "sp-runtime-interface", "sp-staking", "sp-std", ] @@ -6116,6 +6175,28 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-root-offences" +version = "1.0.0" +dependencies = [ + "frame-election-provider-support", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-offences", + "pallet-session", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + [[package]] name = "pallet-scheduler" version = "4.0.0-dev" @@ -6268,7 +6349,7 @@ dependencies = [ "log", "pallet-balances", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "remote-externalities", "scale-info", "serde", @@ -6394,10 +6475,10 @@ dependencies = [ name = "pallet-transaction-storage" version = "4.0.0-dev" dependencies = [ + "array-bytes", "frame-benchmarking", "frame-support", "frame-system", - "hex-literal", "log", "pallet-balances", "parity-scale-codec", @@ -6499,9 +6580,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.13" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55a7901b85874402471e131de3332dde0e51f38432c69a3853627c8e25433048" +checksum = "2bb474d0ed0836e185cb998a6b140ed1073d1fbf27d690ecf9ede8030289382c" dependencies = [ "blake2-rfc", "crc32fast", @@ -6512,7 +6593,7 @@ dependencies = [ "lz4", "memmap2 0.2.1", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "snap", ] @@ -6556,10 +6637,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c32561d248d352148124f036cac253a644685a21dc9fea383eb4907d7bd35a8f" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.12.0", + "hashbrown 0.12.3", "impl-trait-for-tuples", "parity-util-mem-derive", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "primitive-types", "smallvec", "winapi", @@ -6587,9 +6668,9 @@ dependencies = [ [[package]] name = "parity-wasm" -version = "0.42.2" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" [[package]] name = "parking" @@ -6610,9 +6691,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core 0.9.1", @@ -6791,6 +6872,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.19" @@ -7018,7 +7110,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc03e116981ff7d8da8e5c220e374587b98d294af7ba7dd7fda761158f00086f" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.10.1", +] + +[[package]] +name = "prost" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "399c3c31cdec40583bb68f0b18403400d01ec4289c383aa047560439952c4dd7" +dependencies = [ + "bytes", + "prost-derive 0.11.0", ] [[package]] @@ -7036,8 +7138,28 @@ dependencies = [ "log", "multimap", "petgraph", - "prost", - "prost-types", + "prost 0.10.3", + "prost-types 0.10.1", + "regex", + "tempfile", + "which", +] + +[[package]] +name = "prost-build" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f835c582e6bd972ba8347313300219fed5bfa52caf175298d860b61ff6069bb" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prost 0.11.0", + "prost-types 0.11.1", "regex", "tempfile", "which", @@ -7051,7 +7173,7 @@ checksum = "00af1e92c33b4813cc79fda3f2dbf56af5169709be0202df730e9ebc3e4cd007" dependencies = [ "asynchronous-codec", "bytes", - "prost", + "prost 0.10.3", "thiserror", "unsigned-varint", ] @@ -7069,6 +7191,19 @@ dependencies = [ "syn", ] +[[package]] +name = "prost-derive" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7345d5f0e08c0536d7ac7229952590239e77abf0a0100a1b1d890add6ea96364" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "prost-types" version = "0.10.1" @@ -7076,7 +7211,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes", - "prost", + "prost 0.10.3", +] + +[[package]] +name = "prost-types" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dfaa718ad76a44b3415e6c4d53b17c8f99160dcb3a99b10470fce8ad43f6e3e" +dependencies = [ + "bytes", + "prost 0.11.0", ] [[package]] @@ -7126,7 +7271,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -7165,20 +7310,19 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", "rand_pcg 0.2.1", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.0", "rand_core 0.6.2", - "rand_hc 0.3.0", ] [[package]] @@ -7226,7 +7370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -7238,15 +7382,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core 0.6.2", -] - [[package]] name = "rand_pcg" version = "0.2.1" @@ -7348,9 +7483,9 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.2.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d37148700dbb38f994cd99a1431613057f37ed934d7e4d799b7ab758c482461" +checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779" dependencies = [ "fxhash", "log", @@ -7385,18 +7520,6 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" -[[package]] -name = "region" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" -dependencies = [ - "bitflags", - "libc", - "mach", - "winapi", -] - [[package]] name = "region" version = "3.0.0" @@ -7489,7 +7612,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f08c8062c1fe1253064043b8fc07bfea1b9702b71b4a86c11ea3588183b12e1" dependencies = [ "bytecheck", - "hashbrown 0.12.0", + "hashbrown 0.12.3", "ptr_meta", "rend", "rkyv_derive", @@ -7519,9 +7642,9 @@ dependencies = [ [[package]] name = "rpassword" -version = "5.0.1" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" +checksum = "26b763cb66df1c928432cc35053f8bd4cec3335d8559fc16010017d16b3c1680" dependencies = [ "libc", "winapi", @@ -7580,29 +7703,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.33.7" +version = "0.35.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938a344304321a9da4973b9ff4f9f8db9caf4597dfd9dda6a60b523340a0fff0" +checksum = "72c825b8aa8010eb9ee99b75f05e10180b9278d161583034d7574c9d617aeada" dependencies = [ "bitflags", "errno", - "io-lifetimes 0.5.3", + "io-lifetimes", "libc", - "linux-raw-sys 0.0.42", - "winapi", -] - -[[package]] -name = "rustix" -version = "0.35.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef258c11e17f5c01979a10543a30a4e12faef6aab217a74266e747eefa3aed88" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes 0.7.2", - "libc", - "linux-raw-sys 0.0.46", + "linux-raw-sys", "windows-sys 0.36.1", ] @@ -7645,6 +7754,17 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error 1.2.3", + "tempfile", +] + [[package]] name = "rw-stream-sink" version = "0.3.0" @@ -7703,18 +7823,18 @@ dependencies = [ name = "sc-authority-discovery" version = "0.10.0-dev" dependencies = [ + "async-trait", "futures", "futures-timer", "ip_network", "libp2p", "log", "parity-scale-codec", - "prost", - "prost-build", + "prost 0.11.0", + "prost-build 0.11.1", "quickcheck", "rand 0.7.3", "sc-client-api", - "sc-network", "sc-network-common", "sp-api", "sp-authority-discovery", @@ -7736,7 +7856,7 @@ dependencies = [ "futures-timer", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-block-builder", "sc-client-api", "sc-proposer-metrics", @@ -7777,7 +7897,7 @@ dependencies = [ "memmap2 0.5.0", "parity-scale-codec", "sc-chain-spec-derive", - "sc-network", + "sc-network-common", "sc-telemetry", "serde", "serde_json", @@ -7799,11 +7919,11 @@ dependencies = [ name = "sc-cli" version = "0.10.0-dev" dependencies = [ + "array-bytes", "chrono", "clap 3.1.18", "fdlimit", "futures", - "hex", "libp2p", "log", "names", @@ -7815,6 +7935,7 @@ dependencies = [ "sc-client-db", "sc-keystore", "sc-network", + "sc-network-common", "sc-service", "sc-telemetry", "sc-tracing", @@ -7843,7 +7964,7 @@ dependencies = [ "hash-db", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -7868,7 +7989,9 @@ dependencies = [ name = "sc-client-db" version = "0.10.0-dev" dependencies = [ + "criterion", "hash-db", + "kitchensink-runtime", "kvdb", "kvdb-memorydb", "kvdb-rocksdb", @@ -7876,8 +7999,9 @@ dependencies = [ "log", "parity-db", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "quickcheck", + "rand 0.8.5", "sc-client-api", "sc-state-db", "sp-arithmetic", @@ -7901,7 +8025,7 @@ dependencies = [ "futures-timer", "libp2p", "log", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-client-api", "sc-utils", "serde", @@ -7924,7 +8048,7 @@ dependencies = [ "futures", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-block-builder", "sc-client-api", "sc-consensus", @@ -7962,11 +8086,11 @@ dependencies = [ "futures", "log", "merlin", - "num-bigint", + "num-bigint 0.2.6", "num-rational 0.2.4", "num-traits", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", "rand_chacha 0.2.2", "sc-block-builder", @@ -8088,7 +8212,7 @@ dependencies = [ "futures-timer", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-client-api", "sc-consensus", "sp-api", @@ -8123,7 +8247,6 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-state-machine", - "sp-timestamp", "substrate-test-runtime-client", "thiserror", ] @@ -8142,14 +8265,14 @@ dependencies = [ name = "sc-executor" version = "0.10.0-dev" dependencies = [ + "array-bytes", "criterion", "env_logger", - "hex-literal", "lazy_static", "lru", "num_cpus", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "paste 1.0.6", "regex", "sc-executor-common", @@ -8188,7 +8311,6 @@ dependencies = [ "sc-allocator", "sp-maybe-compressed-blob", "sp-sandbox", - "sp-serializer", "sp-wasm-interface", "thiserror", "wasm-instrument", @@ -8219,9 +8341,9 @@ dependencies = [ "log", "once_cell", "parity-scale-codec", - "parity-wasm 0.42.2", + "parity-wasm 0.45.0", "paste 1.0.6", - "rustix 0.35.6", + "rustix", "sc-allocator", "sc-executor-common", "sc-runtime-test", @@ -8239,6 +8361,7 @@ name = "sc-finality-grandpa" version = "0.10.0-dev" dependencies = [ "ahash", + "array-bytes", "assert_matches", "async-trait", "dyn-clone", @@ -8246,11 +8369,10 @@ dependencies = [ "fork-tree", "futures", "futures-timer", - "hex", "log", "parity-scale-codec", - "parking_lot 0.12.0", - "rand 0.8.4", + "parking_lot 0.12.1", + "rand 0.8.5", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -8327,9 +8449,9 @@ dependencies = [ name = "sc-keystore" version = "4.0.0-dev" dependencies = [ + "array-bytes", "async-trait", - "hex", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "serde_json", "sp-application-crypto", "sp-core", @@ -8342,6 +8464,7 @@ dependencies = [ name = "sc-network" version = "0.10.0-dev" dependencies = [ + "array-bytes", "assert_matches", "async-std", "async-trait", @@ -8354,7 +8477,6 @@ dependencies = [ "fork-tree", "futures", "futures-timer", - "hex", "ip_network", "libp2p", "linked-hash-map", @@ -8362,10 +8484,9 @@ dependencies = [ "log", "lru", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project", - "prost", - "prost-build", + "prost 0.11.0", "rand 0.7.3", "sc-block-builder", "sc-client-api", @@ -8391,10 +8512,35 @@ dependencies = [ "tempfile", "thiserror", "unsigned-varint", - "void", "zeroize", ] +[[package]] +name = "sc-network-bitswap" +version = "0.10.0-dev" +dependencies = [ + "cid", + "futures", + "libp2p", + "log", + "prost 0.11.0", + "prost-build 0.11.1", + "sc-block-builder", + "sc-client-api", + "sc-consensus", + "sc-network-common", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-runtime", + "substrate-test-runtime", + "substrate-test-runtime-client", + "thiserror", + "tokio", + "unsigned-varint", + "void", +] + [[package]] name = "sc-network-common" version = "0.10.0-dev" @@ -8403,15 +8549,20 @@ dependencies = [ "bitflags", "bytes", "futures", + "futures-timer", "libp2p", + "linked_hash_set", "parity-scale-codec", - "prost-build", + "prost-build 0.11.1", "sc-consensus", "sc-peerset", + "serde", "smallvec", + "sp-blockchain", "sp-consensus", "sp-finality-grandpa", "sp-runtime", + "substrate-prometheus-endpoint", "thiserror", ] @@ -8427,8 +8578,8 @@ dependencies = [ "log", "lru", "quickcheck", - "sc-network", "sc-network-common", + "sc-peerset", "sp-runtime", "substrate-prometheus-endpoint", "substrate-test-runtime-client", @@ -8439,13 +8590,13 @@ dependencies = [ name = "sc-network-light" version = "0.10.0-dev" dependencies = [ + "array-bytes", "futures", - "hex", "libp2p", "log", "parity-scale-codec", - "prost", - "prost-build", + "prost 0.11.0", + "prost-build 0.11.1", "sc-client-api", "sc-network-common", "sc-peerset", @@ -8459,15 +8610,15 @@ dependencies = [ name = "sc-network-sync" version = "0.10.0-dev" dependencies = [ + "array-bytes", "fork-tree", "futures", - "hex", "libp2p", "log", "lru", "parity-scale-codec", - "prost", - "prost-build", + "prost 0.11.0", + "prost-build 0.11.1", "quickcheck", "sc-block-builder", "sc-client-api", @@ -8497,7 +8648,7 @@ dependencies = [ "futures-timer", "libp2p", "log", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", "sc-block-builder", "sc-client-api", @@ -8517,28 +8668,47 @@ dependencies = [ "substrate-test-runtime-client", ] +[[package]] +name = "sc-network-transactions" +version = "0.10.0-dev" +dependencies = [ + "array-bytes", + "futures", + "hex", + "libp2p", + "log", + "parity-scale-codec", + "pin-project", + "sc-network-common", + "sc-peerset", + "sp-consensus", + "sp-runtime", + "substrate-prometheus-endpoint", +] + [[package]] name = "sc-offchain" version = "4.0.0-dev" dependencies = [ + "array-bytes", "bytes", "fnv", "futures", "futures-timer", - "hex", "hyper", "hyper-rustls", "lazy_static", + "libp2p", "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", "sc-block-builder", "sc-client-api", "sc-client-db", - "sc-network", "sc-network-common", + "sc-peerset", "sc-transaction-pool", "sc-transaction-pool-api", "sc-utils", @@ -8587,11 +8757,12 @@ dependencies = [ "lazy_static", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-block-builder", "sc-chain-spec", "sc-client-api", "sc-network", + "sc-network-common", "sc-rpc-api", "sc-tracing", "sc-transaction-pool", @@ -8621,7 +8792,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-chain-spec", "sc-transaction-pool-api", "scale-info", @@ -8647,6 +8818,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "sc-rpc-spec-v2" +version = "0.10.0-dev" +dependencies = [ + "hex", + "jsonrpsee", + "sc-chain-spec", + "serde_json", + "tokio", +] + [[package]] name = "sc-runtime-test" version = "2.0.0" @@ -8676,7 +8858,7 @@ dependencies = [ "log", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project", "rand 0.7.3", "sc-block-builder", @@ -8688,9 +8870,11 @@ dependencies = [ "sc-informant", "sc-keystore", "sc-network", + "sc-network-bitswap", "sc-network-common", "sc-network-light", "sc-network-sync", + "sc-network-transactions", "sc-offchain", "sc-rpc", "sc-rpc-server", @@ -8720,6 +8904,7 @@ dependencies = [ "sp-transaction-storage-proof", "sp-trie", "sp-version", + "static_init", "substrate-prometheus-endpoint", "substrate-test-runtime", "substrate-test-runtime-client", @@ -8734,13 +8919,12 @@ dependencies = [ name = "sc-service-test" version = "2.0.0" dependencies = [ + "array-bytes", "fdlimit", "futures", - "hex", - "hex-literal", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-block-builder", "sc-client-api", "sc-client-db", @@ -8775,7 +8959,7 @@ dependencies = [ "parity-scale-codec", "parity-util-mem", "parity-util-mem-derive", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-client-api", "sp-core", ] @@ -8824,7 +9008,7 @@ dependencies = [ "futures", "libp2p", "log", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project", "rand 0.7.3", "serde", @@ -8845,7 +9029,7 @@ dependencies = [ "libc", "log", "once_cell", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "regex", "rustc-hash", "sc-client-api", @@ -8878,16 +9062,16 @@ dependencies = [ name = "sc-transaction-pool" version = "4.0.0-dev" dependencies = [ + "array-bytes", "assert_matches", "criterion", "futures", "futures-timer", - "hex", "linked-hash-map", "log", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-block-builder", "sc-client-api", "sc-transaction-pool-api", @@ -8927,7 +9111,7 @@ dependencies = [ "futures-timer", "lazy_static", "log", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "prometheus", "tokio-test", ] @@ -9016,6 +9200,7 @@ checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" dependencies = [ "der", "generic-array 0.14.4", + "pkcs8", "subtle", "zeroize", ] @@ -9144,9 +9329,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa 1.0.1", "ryu", @@ -9364,7 +9549,7 @@ dependencies = [ "futures", "httparse", "log", - "rand 0.8.4", + "rand 0.8.5", "sha-1 0.9.4", ] @@ -9381,6 +9566,7 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-test-primitives", + "sp-trie", "sp-version", "thiserror", ] @@ -9464,7 +9650,7 @@ name = "sp-arithmetic-fuzzer" version = "2.0.0" dependencies = [ "honggfuzz", - "num-bigint", + "num-bigint 0.2.6", "primitive-types", "sp-arithmetic", ] @@ -9511,7 +9697,7 @@ dependencies = [ "log", "lru", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sp-api", "sp-consensus", "sp-database", @@ -9618,18 +9804,17 @@ dependencies = [ name = "sp-core" version = "6.0.0" dependencies = [ + "array-bytes", "base58", "bitflags", - "blake2-rfc", + "blake2", "byteorder", "criterion", "dyn-clonable", - "ed25519-dalek", + "ed25519-zebra", "futures", "hash-db", "hash256-std-hasher", - "hex", - "hex-literal", "impl-serde", "lazy_static", "libsecp256k1", @@ -9638,7 +9823,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "primitive-types", "rand 0.7.3", "regex", @@ -9692,7 +9877,7 @@ name = "sp-database" version = "4.0.0-dev" dependencies = [ "kvdb", - "parking_lot 0.12.0", + "parking_lot 0.12.1", ] [[package]] @@ -9755,7 +9940,7 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "secp256k1", "sp-core", "sp-externalities", @@ -9788,7 +9973,7 @@ dependencies = [ "futures", "merlin", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", "rand_chacha 0.2.2", "schnorrkel", @@ -9810,7 +9995,7 @@ dependencies = [ name = "sp-mmr-primitives" version = "4.0.0-dev" dependencies = [ - "hex-literal", + "array-bytes", "log", "parity-scale-codec", "serde", @@ -9843,7 +10028,7 @@ dependencies = [ "clap 3.1.18", "honggfuzz", "parity-scale-codec", - "rand 0.8.4", + "rand 0.8.5", "scale-info", "sp-npos-elections", "sp-runtime", @@ -9900,6 +10085,7 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-tracing", + "sp-weights", "substrate-test-runtime-client", "zstd", ] @@ -10027,13 +10213,13 @@ dependencies = [ name = "sp-state-machine" version = "0.12.0" dependencies = [ + "array-bytes", "assert_matches", "hash-db", - "hex-literal", "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pretty_assertions", "rand 0.7.3", "smallvec", @@ -10045,6 +10231,7 @@ dependencies = [ "sp-trie", "thiserror", "tracing", + "trie-db", "trie-root", ] @@ -10142,16 +10329,23 @@ dependencies = [ name = "sp-trie" version = "6.0.0" dependencies = [ + "ahash", + "array-bytes", "criterion", "hash-db", - "hex-literal", + "hashbrown 0.12.3", + "lazy_static", + "lru", "memory-db", + "nohash-hasher", "parity-scale-codec", + "parking_lot 0.12.1", "scale-info", "sp-core", "sp-runtime", "sp-std", "thiserror", + "tracing", "trie-bench", "trie-db", "trie-root", @@ -10164,7 +10358,7 @@ version = "5.0.0" dependencies = [ "impl-serde", "parity-scale-codec", - "parity-wasm 0.42.2", + "parity-wasm 0.45.0", "scale-info", "serde", "sp-core-hashing-proc-macro", @@ -10197,17 +10391,42 @@ dependencies = [ "wasmtime", ] +[[package]] +name = "sp-weights" +version = "4.0.0" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-core", + "sp-debug-derive", + "sp-std", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "ss58-registry" -version = "1.18.0" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceb8b72a924ccfe7882d0e26144c114503760a4d1248bb5cd06c8ab2d55404cc" +checksum = "b0837b5d62f42082c9d56cd946495ae273a3c68083b637b9153341d5e465146d" dependencies = [ "Inflector", "num-format", @@ -10230,6 +10449,34 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "static_init" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" +dependencies = [ + "bitflags", + "cfg_aliases", + "libc", + "parking_lot 0.11.2", + "parking_lot_core 0.8.5", + "static_init_macro", + "winapi", +] + +[[package]] +name = "static_init_macro" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf" +dependencies = [ + "cfg_aliases", + "memchr", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "statrs" version = "0.15.0" @@ -10240,7 +10487,7 @@ dependencies = [ "lazy_static", "nalgebra", "num-traits", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -10323,6 +10570,8 @@ dependencies = [ "sc-rpc-api", "scale-info", "serde", + "sp-core", + "sp-runtime", "sp-storage", "tokio", ] @@ -10389,9 +10638,9 @@ dependencies = [ name = "substrate-test-client" version = "2.0.1" dependencies = [ + "array-bytes", "async-trait", "futures", - "hex", "parity-scale-codec", "sc-client-api", "sc-client-db", @@ -10482,7 +10731,7 @@ version = "2.0.0" dependencies = [ "futures", "parity-scale-codec", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "sc-transaction-pool", "sc-transaction-pool-api", "sp-blockchain", @@ -10768,7 +11017,7 @@ dependencies = [ "mio", "num_cpus", "once_cell", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project-lite 0.2.6", "signal-hook-registry", "socket2", @@ -10948,9 +11197,9 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" [[package]] name = "trie-bench" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ecec5d10427b35e9ae374b059dccc0801d02d832617c04c78afc7a8c5c4a34" +checksum = "c5704f0d6130bd83608e4370c19e20c8a6ec03e80363e493d0234efca005265a" dependencies = [ "criterion", "hash-db", @@ -10964,12 +11213,12 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32d034c0d3db64b43c31de38e945f15b40cd4ca6d2dcfc26d4798ce8de4ab83" +checksum = "004e1e8f92535694b4cb1444dc5a8073ecf0815e3357f729638b9f8fc4062908" dependencies = [ "hash-db", - "hashbrown 0.12.0", + "hashbrown 0.12.3", "log", "rustc-hex", "smallvec", @@ -11011,7 +11260,7 @@ dependencies = [ "ipnet", "lazy_static", "log", - "rand 0.8.4", + "rand 0.8.5", "smallvec", "thiserror", "tinyvec", @@ -11030,7 +11279,7 @@ dependencies = [ "lazy_static", "log", "lru-cache", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "resolv-conf", "smallvec", "thiserror", @@ -11048,6 +11297,7 @@ name = "try-runtime-cli" version = "0.10.0-dev" dependencies = [ "clap 3.1.18", + "frame-try-runtime", "jsonrpsee", "log", "parity-scale-codec", @@ -11064,6 +11314,7 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-version", + "tokio", "zstd", ] @@ -11097,7 +11348,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if 1.0.0", "digest 0.10.3", - "rand 0.8.4", + "rand 0.8.5", "static_assertions", ] @@ -11383,11 +11634,11 @@ dependencies = [ [[package]] name = "wasm-instrument" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962e5b0401bbb6c887f54e69b8c496ea36f704df65db73e81fd5ff8dc3e63a9f" +checksum = "aa1dafb3e60065305741e83db35c6c2584bb3725b692b5b66148a38d72ace6cd" dependencies = [ - "parity-wasm 0.42.2", + "parity-wasm 0.45.0", ] [[package]] @@ -11561,7 +11812,7 @@ dependencies = [ "enumset", "leb128", "loupe", - "region 3.0.0", + "region", "rkyv", "wasmer-compiler", "wasmer-engine", @@ -11610,7 +11861,7 @@ dependencies = [ "loupe", "memoffset", "more-asserts", - "region 3.0.0", + "region", "rkyv", "serde", "thiserror", @@ -11620,28 +11871,35 @@ dependencies = [ [[package]] name = "wasmi" -version = "0.9.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca00c5147c319a8ec91ec1a0edbec31e566ce2c9cc93b3f9bb86a9efd0eb795d" +checksum = "fc13b3c219ca9aafeec59150d80d89851df02e0061bc357b4d66fc55a8d38787" dependencies = [ - "downcast-rs", - "errno", - "libc", - "libm", - "memory_units", - "num-rational 0.2.4", - "num-traits", - "parity-wasm 0.42.2", + "parity-wasm 0.45.0", "wasmi-validation", + "wasmi_core", ] [[package]] name = "wasmi-validation" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb8e860796d8be48efef530b60eebf84e74a88bce107374fffb0da97d504b8" +checksum = "91ff416ad1ff0c42e5a926ed5d5fab74c0f098749aa0ad8b2a34b982ce0e867b" dependencies = [ - "parity-wasm 0.42.2", + "parity-wasm 0.45.0", +] + +[[package]] +name = "wasmi_core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a088e8c4c59c6f2b9eae169bf86328adccc477c00b56d3661e3e9fb397b184" +dependencies = [ + "downcast-rs", + "libm", + "memory_units", + "num-rational 0.4.0", + "num-traits", ] [[package]] @@ -11652,49 +11910,55 @@ checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65" [[package]] name = "wasmparser" -version = "0.85.0" +version = "0.89.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570460c58b21e9150d2df0eaaedbb7816c34bcec009ae0dcc976e40ba81463e7" +checksum = "ab5d3e08b13876f96dd55608d03cd4883a0545884932d5adf11925876c96daef" dependencies = [ "indexmap", ] [[package]] name = "wasmtime" -version = "0.38.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c842f9c8e190fe01300fc8d715e9368c775670fb9856247c67abffdb5236d6db" +checksum = "8a10dc9784d8c3a33c970e3939180424955f08af2e7f20368ec02685a0e8f065" dependencies = [ "anyhow", - "backtrace", "bincode", "cfg-if 1.0.0", "indexmap", - "lazy_static", "libc", "log", - "object 0.28.3", + "object 0.29.0", "once_cell", "paste 1.0.6", "psm", "rayon", - "region 2.2.0", "serde", "target-lexicon", - "wasmparser 0.85.0", + "wasmparser 0.89.1", "wasmtime-cache", "wasmtime-cranelift", "wasmtime-environ", "wasmtime-jit", "wasmtime-runtime", - "winapi", + "windows-sys 0.36.1", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4dbdc6daf68528cad1275ac91e3f51848ce9824385facc94c759f529decdf8" +dependencies = [ + "cfg-if 1.0.0", ] [[package]] name = "wasmtime-cache" -version = "0.38.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce2aa752e864a33eef2a6629edc59554e75f0bc1719431dac5e49eed516af69" +checksum = "9f507f3fa1ee1b2f9a83644e2514242b1dfe580782c0eb042f1ef70255bc4ffe" dependencies = [ "anyhow", "base64", @@ -11702,61 +11966,59 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.33.7", + "rustix", "serde", "sha2 0.9.8", "toml", - "winapi", + "windows-sys 0.36.1", "zstd", ] [[package]] name = "wasmtime-cranelift" -version = "0.38.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922361eb8c03cea8909bc922471202f6c6bc2f0c682fac2fe473740441c86b3b" +checksum = "8f03cf79d982fc68e94ba0bea6a300a3b94621c4eb9705eece0a4f06b235a3b5" dependencies = [ "anyhow", - "cranelift-codegen 0.85.0", - "cranelift-entity 0.85.0", - "cranelift-frontend 0.85.0", + "cranelift-codegen 0.88.0", + "cranelift-entity 0.88.0", + "cranelift-frontend 0.88.0", "cranelift-native", "cranelift-wasm", "gimli 0.26.1", "log", - "more-asserts", - "object 0.28.3", + "object 0.29.0", "target-lexicon", "thiserror", - "wasmparser 0.85.0", + "wasmparser 0.89.1", "wasmtime-environ", ] [[package]] name = "wasmtime-environ" -version = "0.38.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e602f1120fc40a3f016f1f69d08c86cfeff7b867bed1462901953e6871f85167" +checksum = "5c587c62e91c5499df62012b87b88890d0eb470b2ffecc5964e9da967b70c77c" dependencies = [ "anyhow", - "cranelift-entity 0.85.0", + "cranelift-entity 0.88.0", "gimli 0.26.1", "indexmap", "log", - "more-asserts", - "object 0.28.3", + "object 0.29.0", "serde", "target-lexicon", "thiserror", - "wasmparser 0.85.0", + "wasmparser 0.89.1", "wasmtime-types", ] [[package]] name = "wasmtime-jit" -version = "0.38.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49af1445759a8e797a92f27dd0983c155615648263052e0b80d69e7d223896b7" +checksum = "047839b5dabeae5424a078c19b8cc897e5943a7fadc69e3d888b9c9a897666b3" dependencies = [ "addr2line", "anyhow", @@ -11765,38 +12027,36 @@ dependencies = [ "cpp_demangle", "gimli 0.26.1", "log", - "object 0.28.3", - "region 2.2.0", + "object 0.29.0", "rustc-demangle", - "rustix 0.33.7", + "rustix", "serde", "target-lexicon", "thiserror", "wasmtime-environ", "wasmtime-jit-debug", "wasmtime-runtime", - "winapi", + "windows-sys 0.36.1", ] [[package]] name = "wasmtime-jit-debug" -version = "0.38.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5dd480cc6dc0a401653e45b79796a3317f8228990d84bc2271bdaf0810071" +checksum = "b299569abf6f99b7b8e020afaf84a700e8636c6a42e242069267322cd5818235" dependencies = [ - "lazy_static", - "object 0.28.3", - "rustix 0.33.7", + "object 0.29.0", + "once_cell", + "rustix", ] [[package]] name = "wasmtime-runtime" -version = "0.38.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e875bcd02d1ecfc7d099dd58354d55d73467652eb2b103ff470fe3aecb7d0381" +checksum = "ae79e0515160bd5abee5df50a16c4eb8db9f71b530fc988ae1d9ce34dcb8dd01" dependencies = [ "anyhow", - "backtrace", "cc", "cfg-if 1.0.0", "indexmap", @@ -11805,26 +12065,26 @@ dependencies = [ "mach", "memfd", "memoffset", - "more-asserts", - "rand 0.8.4", - "region 2.2.0", - "rustix 0.33.7", + "paste 1.0.6", + "rand 0.8.5", + "rustix", "thiserror", + "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", - "winapi", + "windows-sys 0.36.1", ] [[package]] name = "wasmtime-types" -version = "0.38.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd63a19ba61ac7448add4dc1fecb8d78304812af2a52dad04b89f887791b156" +checksum = "790cf43ee8e2d5dad1780af30f00d7a972b74725fb1e4f90c28d62733819b185" dependencies = [ - "cranelift-entity 0.85.0", + "cranelift-entity 0.88.0", "serde", "thiserror", - "wasmparser 0.85.0", + "wasmparser 0.89.1", ] [[package]] @@ -12097,8 +12357,8 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot 0.12.0", - "rand 0.8.4", + "parking_lot 0.12.1", + "rand 0.8.5", "static_assertions", ] diff --git a/Cargo.toml b/Cargo.toml index 1f22343c002a8..59237be64922d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -153,6 +153,7 @@ members = [ "frame/utility", "frame/vesting", "frame/whitelist", + "frame/ibc", "primitives/api", "primitives/api/proc-macro", "primitives/api/test", diff --git a/frame/ibc/Cargo.toml b/frame/ibc/Cargo.toml new file mode 100644 index 0000000000000..15b11038342d5 --- /dev/null +++ b/frame/ibc/Cargo.toml @@ -0,0 +1,84 @@ +[package] +name = 'pallet-ibc' +version = "3.0.0-pre.0" +authors = ['Octopus Network '] +edition = '2021' +license = "Apache-2.0" +homepage = "https://docs.substrate.io/" +repository = "https://github.com/octopus-network/substrate-ibc/" +description = "An IBC implementation on Substrate." +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } +log = { version = "0.4.0", default-features = false } +prost-types = { version = "0.11", default-features = false } +prost = { version = "0.11", default-features = false } +serde_json = { version = "1.0", default-features = false } +serde = { version = "1.0", default-features = false } +flex-error = { version = "0.4.4", default-features = false } +hex = {version = "0.4.0", default-features = false } + +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +sp-tracing = { version = "5.0.0", default-features = false, path = "../../primitives/tracing" } +time = { version = "0.3.11", features = ["macros","parsing"], default-features = false} + +ibc = { version = "0.18.0", default-features = false } +ibc-proto = { version = "0.20.0", default-features = false } +tendermint-proto = { version = "=0.23.9", default-features = false } + +frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } + +[dev-dependencies] +hex = '0.4.0' +sha2 = '0.10.2' +serde = { version = "1.0" } +ibc = { version = "0.18.0", features = ["mocks"] } +sp-io = { version = "6.0.0", path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } +sp-std = { version = "4.0.0", path = "../../primitives/std" } +sp-keyring = { version = "6.0.0", path = "../../primitives/keyring" } +frame-support = { version = "4.0.0-dev", path = "../support" } +pallet-assets = { version = "4.0.0-dev", path = "../assets" } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } +pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } +pallet-babe = { version = "4.0.0-dev", path = "../babe" } +sp-version = { version = "5.0.0", path = "../../primitives/version" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +chrono = "0.4.19" + +[features] +default = ['std'] +std = [ + 'codec/std', + 'log/std', + "scale-info/std", + 'frame-benchmarking/std', + 'frame-support/std', + 'frame-system/std', + 'sp-core/std', + 'sp-runtime/std', + 'sp-std/std', + 'sp-io/std', + 'sp-tracing/std', + 'prost-types/std', + 'prost/std', + 'ibc/std', + 'ibc-proto/std', + 'serde_json/std', + 'serde/std', + 'flex-error/std', + 'hex/std', + 'time/std', +] +runtime-benchmarks = ["frame-benchmarking"] +try-runtime = ["frame-support/try-runtime"] \ No newline at end of file diff --git a/frame/ibc/README.md b/frame/ibc/README.md new file mode 100644 index 0000000000000..2bb71b0b97cd6 --- /dev/null +++ b/frame/ibc/README.md @@ -0,0 +1,17 @@ +# Substrate IBC Pallet (work in progress) + +This project is [funded by Interchain Foundation](https://interchain-io.medium.com/ibc-on-substrate-with-cdot-a7025e521028). + +## Overview + +This pallet implements the standard [IBC protocol](https://github.com/cosmos/ics). + +The goal of this pallet is to allow the blockchains built on Substrate to gain the ability to interact with other chains in a trustless way via IBC protocol. + +The pallet implements the chain specific logic of [ICS spec](https://github.com/cosmos/ibc/tree/51f0c9e8d8ebcbe6f7f023a8b80f65a8fab705e3/spec), and is integrated with [ibc-rs](https://github.com/informalsystems/ibc-rs), which implements the generic cross-chain logic in [ICS spec](https://github.com/cosmos/ibc/tree/51f0c9e8d8ebcbe6f7f023a8b80f65a8fab705e3/spec). + +## Interface + +### Dispatchable Functions +- `deliver` - This function acts as an entry for most of the IBC request. I.e., create clients, update clients, handshakes to create channels, ...etc +- `raw_transfer` - ICS20 fungible token transfer, Handling transfer request as sending chain or receiving chain. \ No newline at end of file diff --git a/frame/ibc/src/context.rs b/frame/ibc/src/context.rs new file mode 100644 index 0000000000000..8508e5e65c650 --- /dev/null +++ b/frame/ibc/src/context.rs @@ -0,0 +1,67 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::*; +use alloc::{ + borrow::{Borrow, Cow, ToOwned}, + collections::BTreeMap, + sync::Arc, +}; +use scale_info::TypeInfo; + +use crate::module::applications::transfer::transfer_handle_callback::TransferModule; +use ibc::{ + applications::transfer::{context::Ics20Context, error::Error as ICS20Error, MODULE_ID_STR}, + core::{ + ics04_channel::{ + channel::{Counterparty, Order}, + error::Error as Ics04Error, + Version, + }, + ics24_host::identifier::{ChannelId, ConnectionId, PortId}, + ics26_routing::context::{ + Ics26Context, Module, ModuleId, ModuleOutputBuilder, RouterBuilder, + }, + }, +}; + +use crate::module::core::ics26_routing::{Router, SubRouterBuilder}; + +/// A struct capturing all the functional dependencies (i.e., context) +/// which the ICS26 module requires to be able to dispatch and process IBC messages. +#[derive(Clone, Debug)] +pub struct Context { + pub _pd: PhantomData, + pub router: Router, +} + +impl Context { + pub fn new() -> Self { + let r = SubRouterBuilder::default() + .add_route(MODULE_ID_STR.parse().unwrap(), TransferModule(PhantomData::)) // register transfer Module + .unwrap() + .build(); + + Self { _pd: PhantomData::default(), router: r } + } +} + +impl Default for Context { + fn default() -> Self { + Self::new() + } +} diff --git a/frame/ibc/src/events.rs b/frame/ibc/src/events.rs new file mode 100644 index 0000000000000..92db60337f2d3 --- /dev/null +++ b/frame/ibc/src/events.rs @@ -0,0 +1,356 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::*; +use core::borrow::Borrow; +use ibc::{core::ics26_routing, events::IbcEvent as RawIbcEvent}; + +/// ibc-rs' `ModuleEvent` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ModuleEvent { + pub kind: Vec, + pub module_name: ModuleId, + pub attributes: Vec, +} + +impl From for ModuleEvent { + fn from(module_event: ibc::events::ModuleEvent) -> Self { + Self { + kind: module_event.kind.as_bytes().to_vec(), + module_name: module_event.module_name.into(), + attributes: module_event.attributes.into_iter().map(|event| event.into()).collect(), + } + } +} + +impl From for ibc::events::ModuleEvent { + fn from(module_event: ModuleEvent) -> Self { + Self { + kind: String::from_utf8(module_event.kind).expect("never failed"), + module_name: module_event.module_name.into(), + attributes: module_event.attributes.into_iter().map(|event| event.into()).collect(), + } + } +} + +/// ibc-rs' `ModuleId` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ModuleId(pub Vec); + +impl From for ModuleId { + fn from(module_id: ics26_routing::context::ModuleId) -> Self { + Self(format!("{}", module_id).as_bytes().to_vec()) + } +} + +impl From for ics26_routing::context::ModuleId { + fn from(module_id: ModuleId) -> Self { + ics26_routing::context::ModuleId::from_str( + &String::from_utf8(module_id.0).expect("Convert From UTF8 Never Faild"), + ) + .expect("should never fiaild") + } +} + +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ModuleEventAttribute { + pub key: Vec, + pub value: Vec, +} + +impl From for ModuleEventAttribute { + fn from(module_event_attribute: ibc::events::ModuleEventAttribute) -> Self { + Self { + key: module_event_attribute.key.as_bytes().to_vec(), + value: module_event_attribute.value.as_bytes().to_vec(), + } + } +} + +impl From for ibc::events::ModuleEventAttribute { + fn from(module_event_attribute: ModuleEventAttribute) -> Self { + Self { + key: String::from_utf8(module_event_attribute.key).expect("should not be faild"), + value: String::from_utf8(module_event_attribute.value).expect("should not be faild"), + } + } +} + +impl From for Event { + fn from(value: RawIbcEvent) -> Self { + match value { + RawIbcEvent::NewBlock(value) => Event::::NewBlock { height: value.height.into() }, + RawIbcEvent::CreateClient(value) => { + let height = value.0.height; + let client_id = value.0.client_id; + let client_type = value.0.client_type; + let consensus_height = value.0.consensus_height; + Event::::CreateClient { + height: height.into(), + client_id: client_id.into(), + client_type: client_type.into(), + consensus_height: consensus_height.into(), + } + }, + RawIbcEvent::UpdateClient(value) => { + let height = value.common.height; + let client_id = value.common.client_id; + let client_type = value.common.client_type; + let consensus_height = value.common.consensus_height; + Event::::UpdateClient { + height: height.into(), + client_id: client_id.into(), + client_type: client_type.into(), + consensus_height: consensus_height.into(), + } + }, + // Upgrade client events are not currently being used + RawIbcEvent::UpgradeClient(value) => { + let height = value.0.height; + let client_id = value.0.client_id; + let client_type = value.0.client_type; + let consensus_height = value.0.consensus_height; + Event::::UpgradeClient { + height: height.into(), + client_id: client_id.into(), + client_type: client_type.into(), + consensus_height: consensus_height.into(), + } + }, + RawIbcEvent::ClientMisbehaviour(value) => { + let height = value.0.height; + let client_id = value.0.client_id; + let client_type = value.0.client_type; + let consensus_height = value.0.consensus_height; + Event::::ClientMisbehaviour { + height: height.into(), + client_id: client_id.into(), + client_type: client_type.into(), + consensus_height: consensus_height.into(), + } + }, + RawIbcEvent::OpenInitConnection(value) => { + let height = value.attributes().height; + let connection_id: Option = + value.attributes().connection_id.clone().map(|val| val.into()); + let client_id = value.attributes().client_id.clone(); + let counterparty_connection_id: Option = + value.attributes().counterparty_connection_id.clone().map(|val| val.into()); + + let counterparty_client_id = value.attributes().counterparty_client_id.clone(); + Event::::OpenInitConnection { + height: height.into(), + connection_id, + client_id: client_id.into(), + counterparty_connection_id, + counterparty_client_id: counterparty_client_id.into(), + } + }, + RawIbcEvent::OpenTryConnection(value) => { + let height = value.attributes().height; + let connection_id: Option = + value.attributes().connection_id.clone().map(|val| val.into()); + let client_id = value.attributes().client_id.clone(); + let counterparty_connection_id: Option = + value.attributes().counterparty_connection_id.clone().map(|val| val.into()); + + let counterparty_client_id = value.attributes().counterparty_client_id.clone(); + Event::::OpenTryConnection { + height: height.into(), + connection_id, + client_id: client_id.into(), + counterparty_connection_id, + counterparty_client_id: counterparty_client_id.into(), + } + }, + RawIbcEvent::OpenAckConnection(value) => { + let height = value.attributes().height; + let connection_id: Option = + value.attributes().connection_id.clone().map(|val| val.into()); + let client_id = value.attributes().client_id.clone(); + let counterparty_connection_id: Option = + value.attributes().counterparty_connection_id.clone().map(|val| val.into()); + + let counterparty_client_id = value.attributes().counterparty_client_id.clone(); + Event::::OpenAckConnection { + height: height.into(), + connection_id, + client_id: client_id.into(), + counterparty_connection_id, + counterparty_client_id: counterparty_client_id.into(), + } + }, + RawIbcEvent::OpenConfirmConnection(value) => { + let height = value.attributes().height; + let connection_id: Option = + value.attributes().connection_id.clone().map(|val| val.into()); + let client_id = value.attributes().client_id.clone(); + let counterparty_connection_id: Option = + value.attributes().counterparty_connection_id.clone().map(|val| val.into()); + + let counterparty_client_id = value.attributes().counterparty_client_id.clone(); + Event::::OpenConfirmConnection { + height: height.into(), + connection_id, + client_id: client_id.into(), + counterparty_connection_id, + counterparty_client_id: counterparty_client_id.into(), + } + }, + RawIbcEvent::OpenInitChannel(value) => { + let height = value.height; + let port_id = value.port_id.clone(); + let channel_id: Option = value.channel_id.clone().map(|val| val.into()); + let connection_id = value.connection_id.clone(); + let counterparty_port_id = value.counterparty_port_id.clone(); + let counterparty_channel_id: Option = + value.channel_id.map(|val| val.into()); + Event::::OpenInitChannel { + height: height.into(), + port_id: port_id.into(), + channel_id, + connection_id: connection_id.into(), + counterparty_port_id: counterparty_port_id.into(), + counterparty_channel_id, + } + }, + RawIbcEvent::OpenTryChannel(value) => { + let height = value.height; + let port_id = value.port_id.clone(); + let channel_id: Option = value.channel_id.clone().map(|val| val.into()); + let connection_id = value.connection_id.clone(); + let counterparty_port_id = value.counterparty_port_id.clone(); + let counterparty_channel_id: Option = + value.channel_id.map(|val| val.into()); + Event::::OpenTryChannel { + height: height.into(), + port_id: port_id.into(), + channel_id, + connection_id: connection_id.into(), + counterparty_port_id: counterparty_port_id.into(), + counterparty_channel_id, + } + }, + RawIbcEvent::OpenAckChannel(value) => { + let height = value.height; + let port_id = value.port_id.clone(); + let channel_id: Option = value.channel_id.clone().map(|val| val.into()); + let connection_id = value.connection_id.clone(); + let counterparty_port_id = value.counterparty_port_id.clone(); + let counterparty_channel_id: Option = + value.channel_id.map(|val| val.into()); + Event::::OpenAckChannel { + height: height.into(), + port_id: port_id.into(), + channel_id, + connection_id: connection_id.into(), + counterparty_port_id: counterparty_port_id.into(), + counterparty_channel_id, + } + }, + RawIbcEvent::OpenConfirmChannel(value) => { + let height = value.height; + let port_id = value.port_id.clone(); + let channel_id: Option = value.channel_id.clone().map(|val| val.into()); + let connection_id = value.connection_id.clone(); + let counterparty_port_id = value.counterparty_port_id; + let counterparty_channel_id: Option = + value.channel_id.map(|val| val.into()); + Event::::OpenConfirmChannel { + height: height.into(), + port_id: port_id.into(), + channel_id, + connection_id: connection_id.into(), + counterparty_port_id: counterparty_port_id.into(), + counterparty_channel_id, + } + }, + RawIbcEvent::CloseInitChannel(value) => { + let height = value.height; + let port_id = value.port_id.clone(); + let channel_id: Option = Some(value.channel_id.into()); + let connection_id = value.connection_id.clone(); + let counterparty_port_id = value.counterparty_port_id; + let counterparty_channel_id: Option = + value.counterparty_channel_id.map(|val| val.into()); + Event::::CloseInitChannel { + height: height.into(), + port_id: port_id.into(), + channel_id, + connection_id: connection_id.into(), + counterparty_port_id: counterparty_port_id.into(), + counterparty_channel_id, + } + }, + RawIbcEvent::CloseConfirmChannel(value) => { + let height = value.height; + let port_id = value.port_id.clone(); + let channel_id: Option = value.channel_id.clone().map(|val| val.into()); + let connection_id = value.connection_id.clone(); + let counterparty_port_id = value.counterparty_port_id.clone(); + let counterparty_channel_id: Option = + value.channel_id.map(|val| val.into()); + Event::::CloseConfirmChannel { + height: height.into(), + port_id: port_id.into(), + channel_id, + connection_id: connection_id.into(), + counterparty_port_id: counterparty_port_id.into(), + counterparty_channel_id, + } + }, + RawIbcEvent::SendPacket(value) => { + let height = value.height; + let packet = value.packet; + Event::::SendPacket { height: height.into(), packet: packet.into() } + }, + RawIbcEvent::ReceivePacket(value) => { + let height = value.height; + let packet = value.packet; + Event::::ReceivePacket { height: height.into(), packet: packet.into() } + }, + RawIbcEvent::WriteAcknowledgement(value) => { + let height = value.height; + let packet = value.packet; + let ack = value.ack; + + Event::::WriteAcknowledgement { + height: height.into(), + packet: packet.into(), + ack, + } + }, + RawIbcEvent::AcknowledgePacket(value) => { + let height = value.height; + let packet = value.packet; + Event::::AcknowledgePacket { height: height.into(), packet: packet.into() } + }, + RawIbcEvent::TimeoutPacket(value) => { + let height = value.height; + let packet = value.packet; + Event::::TimeoutPacket { height: height.into(), packet: packet.into() } + }, + RawIbcEvent::TimeoutOnClosePacket(value) => { + let height = value.height; + let packet = value.packet; + Event::::TimeoutOnClosePacket { height: height.into(), packet: packet.into() } + }, + RawIbcEvent::AppModule(value) => Event::::AppModule(value.into()), + RawIbcEvent::ChainError(value) => Event::::ChainError(value.as_bytes().to_vec()), + } + } +} diff --git a/frame/ibc/src/lib.rs b/frame/ibc/src/lib.rs new file mode 100644 index 0000000000000..867e0e7917542 --- /dev/null +++ b/frame/ibc/src/lib.rs @@ -0,0 +1,672 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! # Substrate IBC Pallet (work in progress) +//! +//! This project is [funded by Interchain Foundation](https://interchain-io.medium.com/ibc-on-substrate-with-cdot-a7025e521028). +//! +//! ## Overview +//! +//! This pallet implements the standard [IBC protocol](https://github.com/cosmos/ics). +//! +//! The goal of this pallet is to allow the blockchains built on Substrate to gain the ability to +//! interact with other chains in a trustless way via IBC protocol. +//! +//! The pallet implements the chain specific logic of [ICS spec](https://github.com/cosmos/ibc/tree/51f0c9e8d8ebcbe6f7f023a8b80f65a8fab705e3/spec), and is integrated with [ibc-rs](https://github.com/informalsystems/ibc-rs), which implements the generic cross-chain logic in [ICS spec](https://github.com/cosmos/ibc/tree/51f0c9e8d8ebcbe6f7f023a8b80f65a8fab705e3/spec). +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! - `deliver` - This function acts as an entry for most of the IBC request. I.e., create clients, +//! update clients, handshakes to create channels, ...etc +//! - `raw_transfer` - ICS20 fungible token transfer, Handling transfer request as sending chain or +//! receiving chain. + +#![cfg_attr(not(feature = "std"), no_std)] +// todo need in future to remove +#![allow(unreachable_code)] +#![allow(unreachable_patterns)] +#![allow(clippy::type_complexity)] +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_imports)] +#![allow(unused_variables)] +#![allow(clippy::too_many_arguments)] + +extern crate alloc; +extern crate core; + +pub use pallet::*; + +use alloc::{ + format, + string::{String, ToString}, +}; +use core::{marker::PhantomData, str::FromStr}; +use scale_info::{prelude::vec, TypeInfo}; +use serde::{Deserialize, Serialize}; + +use codec::{Codec, Decode, Encode}; + +use frame_support::{ + sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion}, + sp_std::fmt::Debug, + traits::{tokens::fungibles, Currency, ExistenceRequirement::AllowDeath}, + PalletId, +}; +use frame_system::ensure_signed; +use sp_runtime::{traits::AccountIdConversion, DispatchError, RuntimeDebug, TypeId}; +use sp_std::prelude::*; + +use ibc::{ + applications::transfer::msgs::transfer::MsgTransfer, + core::{ + ics02_client::{client_state::AnyClientState, height}, + ics04_channel::timeout::TimeoutHeight, + ics24_host::identifier::{self, ChainId as ICS24ChainId, ChannelId as IbcChannelId}, + ics26_routing::msgs::Ics26Envelope, + }, + timestamp, + tx_msg::Msg, +}; + +use tendermint_proto::Protobuf; + +pub mod context; +pub mod events; +pub mod module; +pub mod traits; +pub mod utils; + +use crate::{context::Context, traits::AssetIdAndNameProvider}; + +use crate::module::core::ics24_host::{ + ChannelId, ClientId, ClientType, ConnectionId, Height, Packet, PortId, Timestamp, +}; + +pub const REVISION_NUMBER: u64 = 8888; + +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + +/// A struct corresponds to `Any` in crate "prost-types", used in ibc-rs. +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct Any { + pub type_url: Vec, + pub value: Vec, +} + +impl From for Any { + fn from(any: ibc_proto::google::protobuf::Any) -> Self { + Self { type_url: any.type_url.as_bytes().to_vec(), value: any.value } + } +} + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use crate::{ + events::ModuleEvent, + module::{ + applications::transfer::transfer_handle_callback::TransferModule, + core::ics24_host::{ + ChannelId, ClientId, ClientType, ConnectionId, Height, Packet, PortId, Sequence, + Timestamp, + }, + }, + }; + use frame_support::{ + dispatch::DispatchResult, + pallet_prelude::*, + traits::{ + fungibles::{Inspect, Mutate, Transfer}, + UnixTime, + }, + }; + use frame_system::pallet_prelude::*; + use ibc::{ + applications::transfer::context::Ics20Context, + core::{ + ics02_client::client_consensus::AnyConsensusState, + ics04_channel::{ + channel::{Counterparty, Order}, + context::ChannelKeeper, + events::WriteAcknowledgement, + Version, + }, + ics24_host::{ + identifier::{ChannelId as IbcChannelId, PortId as IbcPortId}, + path::{ClientConsensusStatePath, ClientStatePath}, + }, + ics26_routing::error::Error as Ics26Error, + }, + events::IbcEvent, + handler::{HandlerOutput, HandlerOutputBuilder}, + signer::Signer, + }; + use sp_runtime::traits::IdentifyAccount; + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config + Sync + Send + Debug { + /// The overarching event type. + type Event: From> + IsType<::Event>; + + /// The provider providing timestamp of host chain + type TimeProvider: UnixTime; + + /// The currency type of the runtime + type Currency: Currency; + + /// Identifier for the class of asset. + type AssetId: Member + + Parameter + + AtLeast32BitUnsigned + + Codec + + Copy + + Debug + + Default + + MaybeSerializeDeserialize; + + /// The units in which we record balances. + type AssetBalance: Parameter + + Member + + AtLeast32BitUnsigned + + Codec + + Default + + From + + Into + + Copy + + MaybeSerializeDeserialize + + Debug; + + /// Expose customizable associated type of asset transfer, lock and unlock + type Assets: Transfer + + Mutate + + Inspect; + + /// Map of cross-chain asset ID & name + type AssetIdByName: AssetIdAndNameProvider; + + /// Account Id Conversion from SS58 string or hex string + type AccountIdConversion: TryFrom + + IdentifyAccount + + Clone + + PartialEq + + Debug; + + // The native token name + const NATIVE_TOKEN_NAME: &'static [u8]; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::storage] + /// ClientStatePath(client_id) => ClientState + pub type ClientStates = + StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + /// (client_id, height) => timestamp + pub type ClientProcessedTimes = StorageDoubleMap< + _, + Blake2_128Concat, + Vec, + Blake2_128Concat, + Vec, + Vec, + ValueQuery, + >; + + #[pallet::storage] + /// (client_id, height) => host_height + pub type ClientProcessedHeights = StorageDoubleMap< + _, + Blake2_128Concat, + Vec, + Blake2_128Concat, + Vec, + Vec, + ValueQuery, + >; + + #[pallet::storage] + /// ClientConsensusStatePath(client_id, Height) => ConsensusState + pub type ConsensusStates = + StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + /// ConnectionsPath(connection_id) => ConnectionEnd + pub type Connections = StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + /// ChannelEndPath(port_id, channel_id) => ChannelEnd + pub type Channels = StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + /// ConnectionsPath(connection_id) => Vec + pub type ChannelsConnection = + StorageMap<_, Blake2_128Concat, Vec, Vec>, ValueQuery>; + + #[pallet::storage] + /// SeqSendsPath(port_id, channel_id) => sequence + pub type NextSequenceSend = + StorageMap<_, Blake2_128Concat, Vec, u64, ValueQuery>; + + #[pallet::storage] + /// SeqRecvsPath(port_id, channel_id) => sequence + pub type NextSequenceRecv = + StorageMap<_, Blake2_128Concat, Vec, u64, ValueQuery>; + + #[pallet::storage] + /// SeqAcksPath(port_id, channel_id) => sequence + pub type NextSequenceAck = StorageMap<_, Blake2_128Concat, Vec, u64, ValueQuery>; + + #[pallet::storage] + /// AcksPath(port_id, channel_id, sequence) => hash of acknowledgement + pub type Acknowledgements = + StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + /// ClientTypePath(client_id) => client_type + pub type Clients = StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn client_counter)] + /// client counter + pub type ClientCounter = StorageValue<_, u64, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn connection_counter)] + /// connection counter + pub type ConnectionCounter = StorageValue<_, u64, ValueQuery>; + + #[pallet::storage] + /// channel counter + pub type ChannelCounter = StorageValue<_, u64, ValueQuery>; + + #[pallet::storage] + /// ClientConnectionsPath(client_id) => connection_id + pub type ConnectionClient = + StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + /// ReceiptsPath(port_id, channel_id, sequence) => receipt + pub type PacketReceipt = + StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + /// CommitmentsPath(port_id, channel_id, sequence) => hash of (timestamp, height, packet) + pub type PacketCommitment = + StorageMap<_, Blake2_128Concat, Vec, Vec, ValueQuery>; + + #[pallet::storage] + /// (height, port_id, channel_id, sequence) => send-packet event + pub type SendPacketEvent = StorageNMap< + _, + ( + NMapKey>, + NMapKey>, + NMapKey, + ), + Vec, + ValueQuery, + >; + + #[pallet::storage] + /// (port_id, channel_id, sequence) => writ ack event + pub type WriteAckPacketEvent = StorageNMap< + _, + ( + NMapKey>, + NMapKey>, + NMapKey, + ), + Vec, + ValueQuery, + >; + + #[pallet::storage] + /// Latest height + pub type LatestHeight = StorageValue<_, Vec, ValueQuery>; + + #[pallet::storage] + /// Previous host block height + pub type OldHeight = StorageValue<_, u64, ValueQuery>; + + #[pallet::storage] + /// (asset name) => asset id + pub type AssetIdByName = + StorageMap<_, Twox64Concat, Vec, T::AssetId, ValueQuery>; + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub asset_id_by_name: Vec<(String, T::AssetId)>, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { asset_id_by_name: Vec::new() } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + for (token_id, id) in self.asset_id_by_name.iter() { + >::insert(token_id.as_bytes(), id); + } + } + } + + /// Substrate IBC event list + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// New block + NewBlock { height: Height }, + /// Client Create + CreateClient { + height: Height, + client_id: ClientId, + client_type: ClientType, + consensus_height: Height, + }, + /// Client update + UpdateClient { + height: Height, + client_id: ClientId, + client_type: ClientType, + consensus_height: Height, + }, + /// Client upgraded + UpgradeClient { + height: Height, + client_id: ClientId, + client_type: ClientType, + consensus_height: Height, + }, + /// Client misbehaviour + ClientMisbehaviour { + height: Height, + client_id: ClientId, + client_type: ClientType, + consensus_height: Height, + }, + /// Connection open init + OpenInitConnection { + height: Height, + connection_id: Option, + client_id: ClientId, + counterparty_connection_id: Option, + counterparty_client_id: ClientId, + }, + /// Connection open try + OpenTryConnection { + height: Height, + connection_id: Option, + client_id: ClientId, + counterparty_connection_id: Option, + counterparty_client_id: ClientId, + }, + /// Connection open ack + OpenAckConnection { + height: Height, + connection_id: Option, + client_id: ClientId, + counterparty_connection_id: Option, + counterparty_client_id: ClientId, + }, + /// Connection open confirm + OpenConfirmConnection { + height: Height, + connection_id: Option, + client_id: ClientId, + counterparty_connection_id: Option, + counterparty_client_id: ClientId, + }, + /// Channel open init + OpenInitChannel { + height: Height, + port_id: PortId, + channel_id: Option, + connection_id: ConnectionId, + counterparty_port_id: PortId, + counterparty_channel_id: Option, + }, + /// Channel open try + OpenTryChannel { + height: Height, + port_id: PortId, + channel_id: Option, + connection_id: ConnectionId, + counterparty_port_id: PortId, + counterparty_channel_id: Option, + }, + /// Channel open ack + OpenAckChannel { + height: Height, + port_id: PortId, + channel_id: Option, + connection_id: ConnectionId, + counterparty_port_id: PortId, + counterparty_channel_id: Option, + }, + /// Channel open confirm + OpenConfirmChannel { + height: Height, + port_id: PortId, + channel_id: Option, + connection_id: ConnectionId, + counterparty_port_id: PortId, + counterparty_channel_id: Option, + }, + /// Channel close init + CloseInitChannel { + height: Height, + port_id: PortId, + channel_id: Option, + connection_id: ConnectionId, + counterparty_port_id: PortId, + counterparty_channel_id: Option, + }, + /// Channel close confirm + CloseConfirmChannel { + height: Height, + port_id: PortId, + channel_id: Option, + connection_id: ConnectionId, + counterparty_port_id: PortId, + counterparty_channel_id: Option, + }, + /// Send packet + SendPacket { height: Height, packet: Packet }, + /// Receive packet + ReceivePacket { height: Height, packet: Packet }, + /// WriteAcknowledgement packet + WriteAcknowledgement { height: Height, packet: Packet, ack: Vec }, + /// Acknowledgements packet + AcknowledgePacket { height: Height, packet: Packet }, + /// Timeout packet + TimeoutPacket { height: Height, packet: Packet }, + /// TimoutOnClose packet + TimeoutOnClosePacket { height: Height, packet: Packet }, + /// Chain error + ChainError(Vec), + /// App Module + AppModule(ModuleEvent), + /// Transfer native token + TransferNativeToken(T::AccountIdConversion, T::AccountIdConversion, BalanceOf), + /// Transfer non-native token + TransferNoNativeToken( + T::AccountIdConversion, + T::AccountIdConversion, + ::AssetBalance, + ), + /// Burn cross chain token + BurnToken(T::AssetId, T::AccountIdConversion, T::AssetBalance), + /// Mint chairperson token + MintToken(T::AssetId, T::AccountIdConversion, T::AssetBalance), + } + + /// Errors in MMR verification informing users that something went wrong. + #[pallet::error] + pub enum Error { + /// Invalid token id + InvalidTokenId, + /// Wrong assert id + WrongAssetId, + // Parser Msg Transfer Error + ParserMsgTransferError, + } + + /// Dispatchable functions allows users to interact with the pallet and invoke state changes. + /// These functions materialize as "extrinsic", which are often compared to transactions. + /// Dispatch able functions must be annotated with a weight and must return a DispatchResult. + #[pallet::call] + impl Pallet { + /// This function acts as an entry for most of the IBC request. + /// I.e., create clients, update clients, handshakes to create channels, ...etc + /// + /// The origin must be Signed and the sender must have sufficient funds fee. + /// + /// Parameters: + /// - `messages`: The arbitrary ICS message's representation in Substrate, which contains an + /// URL and + /// a serialized protocol buffer message. The URL name that uniquely identifies the type of + /// the serialized protocol buffer message. + /// + /// The relevant events are emitted when successful. + #[pallet::weight(0)] + pub fn deliver(origin: OriginFor, messages: Vec) -> DispatchResultWithPostInfo { + let _sender = ensure_signed(origin)?; + let mut ctx = Context::::new(); + + let messages: Vec = messages + .into_iter() + .map(|message| ibc_proto::google::protobuf::Any { + type_url: String::from_utf8(message.type_url.clone()) + .expect("Convert From UTF8 Never Faild"), + value: message.value, + }) + .collect(); + + for (_, message) in messages.clone().into_iter().enumerate() { + match ibc::core::ics26_routing::handler::deliver(&mut ctx, message.clone()) { + Ok(ibc::core::ics26_routing::handler::MsgReceipt { events, log: _log }) => { + // deposit events about send packet event and ics20 transfer event + for event in events { + Self::deposit_event(event.clone().into()); + } + }, + Err(error) => { + log::error!("deliver error : {:?} ", error); + }, + }; + } + + Ok(().into()) + } + + /// ICS20 fungible token transfer. + /// Handling transfer request as sending chain or receiving chain. + /// + /// Parameters: + /// - `messages`: A serialized protocol buffer message containing the transfer request. + /// + /// The relevant events are emitted when successful. + #[pallet::weight(0)] + pub fn raw_transfer( + origin: OriginFor, + messages: Vec, + ) -> DispatchResultWithPostInfo { + let _sender = ensure_signed(origin)?; + let mut ctx = TransferModule(PhantomData::); + + let messages: Vec = messages + .into_iter() + .map(|message| ibc_proto::google::protobuf::Any { + type_url: String::from_utf8(message.type_url.clone()) + .expect("Convert From UTF8 Never Faild"), + value: message.value, + }) + .collect(); + for message in messages { + let mut handle_out = HandlerOutputBuilder::new(); + let msg_transfer = MsgTransfer::try_from(message) + .map_err(|_| Error::::ParserMsgTransferError)?; + let result = ibc::applications::transfer::relay::send_transfer::send_transfer( + &mut ctx, + &mut handle_out, + msg_transfer, + ); + match result { + Ok(_value) => { + log::trace!("raw_transfer Successful!"); + }, + Err(error) => { + log::trace!("raw_transfer Error : {:?} ", error); + }, + } + + let HandlerOutput::<()> { result, log, events } = handle_out.with_result(()); + + // deposit events about send packet event and ics20 transfer event + for event in events { + Self::deposit_event(event.clone().into()); + } + } + + Ok(().into()) + } + } +} + +impl AssetIdAndNameProvider for Pallet { + type Err = Error; + + fn try_get_asset_id(name: impl AsRef<[u8]>) -> Result<::AssetId, Self::Err> { + let asset_id = >::try_get(name.as_ref().to_vec()); + match asset_id { + Ok(id) => Ok(id), + _ => Err(Error::::InvalidTokenId), + } + } + + fn try_get_asset_name(asset_id: T::AssetId) -> Result, Self::Err> { + let token_id = >::iter().find(|p| p.1 == asset_id).map(|p| p.0); + match token_id { + Some(id) => Ok(id), + _ => Err(Error::::WrongAssetId), + } + } +} + +pub fn from_channel_id_to_vec(value: IbcChannelId) -> Vec { + value.to_string().as_bytes().to_vec() +} diff --git a/frame/ibc/src/mock.rs b/frame/ibc/src/mock.rs new file mode 100644 index 0000000000000..2ce8fa8c563c6 --- /dev/null +++ b/frame/ibc/src/mock.rs @@ -0,0 +1,235 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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. + +//! Test utilities + +use crate as pallet_ibc; +pub use frame_support::{ + construct_runtime, parameter_types, + traits::{ + ConstU128, ConstU16, ConstU32, ConstU8, KeyOwnerProofSystem, Randomness, StorageInfo, + }, + weights::{ + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, + DispatchClass, IdentityFee, Weight, + }, + StorageValue, +}; +use frame_system as system; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureRoot, +}; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256}; +use sp_runtime::{ + create_runtime_str, + generic::{self, Era}, + testing::Header, + traits::{AccountIdLookup, BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, + MultiSignature, +}; +use sp_version::RuntimeVersion; +use std::time::{Duration, Instant}; + +pub type Signature = MultiSignature; +pub(crate) type AccountId = <::Signer as IdentifyAccount>::AccountId; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Assets: pallet_assets::, + Balances: pallet_balances, + Ibc: pallet_ibc, + } +); + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +/// Index of a transaction in the chain. +pub type Index = u32; +/// An index to a block. +pub type BlockNumber = u32; + +impl frame_system::Config for Test { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = frame_support::traits::Everything; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = (); + /// The maximum length of a block (in bytes). + type BlockLength = (); + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type Call = Call; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous origin type. + type Origin = Origin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = (); + /// The weight of database operations that the runtime can invoke. + type DbWeight = (); + /// Version of the runtime. + type Version = (); + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type PalletInfo = PalletInfo; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = ConstU16<42>; + /// The set code logic, just the default since we're not a parachain. + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +pub type Balance = u128; +/// Type used for expressing timestamp. +pub type Moment = u64; + +pub const MILLICENTS: Balance = 10_000_000_000_000; +pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. +pub const DOLLARS: Balance = 100 * CENTS; + +parameter_types! { + pub const AssetDeposit: Balance = 100 * DOLLARS; + pub const ApprovalDeposit: Balance = 1 * DOLLARS; + pub const StringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = 10 * DOLLARS; + pub const MetadataDepositPerByte: Balance = 1 * DOLLARS; +} + +impl pallet_assets::Config for Test { + type Event = Event; + type Balance = AssetBalance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type AssetAccountDeposit = ConstU128; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = StringLimit; + type Freezer = (); + type Extra = (); + type WeightInfo = pallet_assets::weights::SubstrateWeight; +} + +parameter_types! { + pub const ExistentialDeposit: Balance = 1 * DOLLARS; + // For weight estimation, we assume that the most locks on an individual account will be 50. + // This number may need to be adjusted in the future if this assumption no longer holds true. + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Test { + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = frame_system::Pallet; + type WeightInfo = pallet_balances::weights::SubstrateWeight; +} + +parameter_types! { + pub const MinimumPeriod: Moment = SLOT_DURATION / 2; +} + +impl pallet_timestamp::Config for Test { + /// A timestamp: milliseconds since the unix epoch. + type Moment = Moment; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +parameter_types! { + pub const MaxAuthorities: u32 = 100; + pub const MaxKeys: u32 = 10_000; + pub const MaxPeerInHeartbeats: u32 = 10_000; + pub const MaxPeerDataEncodingSize: u32 = 1_000; +} + +pub const MILLISECS_PER_BLOCK: Moment = 6000; +pub const SECS_PER_BLOCK: Moment = MILLISECS_PER_BLOCK / 1000; + +// NOTE: Currently it is not possible to change the slot duration after the chain has started. +// Attempting to do so will brick block production. +pub const SLOT_DURATION: Moment = MILLISECS_PER_BLOCK; + +// 1 in 4 blocks (on average, not counting collisions) will be primary BABE blocks. +pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); + +pub type AssetBalance = u128; +pub type AssetId = u32; + +impl super::pallet::Config for Test { + type Event = Event; + type TimeProvider = pallet_timestamp::Pallet; + type Currency = Balances; + type AssetId = AssetId; + type AssetBalance = AssetBalance; + type Assets = Assets; + type AssetIdByName = Ibc; + type AccountIdConversion = pallet_ibc::module::applications::transfer::IbcAccount; + const NATIVE_TOKEN_NAME: &'static [u8] = b"DEMO"; +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + system::GenesisConfig::default().build_storage::().unwrap().into() +} diff --git a/frame/ibc/src/module/applications/mod.rs b/frame/ibc/src/module/applications/mod.rs new file mode 100644 index 0000000000000..dc8a5fa54cd3a --- /dev/null +++ b/frame/ibc/src/module/applications/mod.rs @@ -0,0 +1,18 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 mod transfer; diff --git a/frame/ibc/src/module/applications/transfer/channel.rs b/frame/ibc/src/module/applications/transfer/channel.rs new file mode 100644 index 0000000000000..7d116fff5e906 --- /dev/null +++ b/frame/ibc/src/module/applications/transfer/channel.rs @@ -0,0 +1,302 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use super::transfer_handle_callback::TransferModule; +use crate::*; +use core::{str::FromStr, time::Duration}; +use log::{error, info, trace, warn}; + +use crate::context::Context; +use ibc::{ + core::{ + ics02_client::{ + client_consensus::AnyConsensusState, client_state::AnyClientState, + context::ClientReader, + }, + ics03_connection::{ + connection::ConnectionEnd, context::ConnectionReader, error::Error as ICS03Error, + }, + ics04_channel::{ + channel::ChannelEnd, + commitment::{ + AcknowledgementCommitment as IbcAcknowledgementCommitment, + PacketCommitment as IbcPacketCommitment, + }, + context::{ChannelKeeper, ChannelReader}, + error::Error as Ics04Error, + packet::{Receipt, Sequence}, + }, + ics05_port::{context::PortReader, error::Error as Ics05Error}, + ics24_host::{ + identifier::{ChannelId, ClientId, ConnectionId, PortId}, + path::{ + AcksPath, ChannelEndsPath, CommitmentsPath, ConnectionsPath, ReceiptsPath, + SeqAcksPath, SeqRecvsPath, SeqSendsPath, + }, + Path, + }, + ics26_routing::context::ModuleId, + }, + timestamp::Timestamp, + Height, +}; + +impl ChannelReader for TransferModule { + fn channel_end(&self, port_channel_id: &(PortId, ChannelId)) -> Result { + let connect = Context::::new(); + connect.channel_end(port_channel_id) + } + + fn connection_end(&self, connection_id: &ConnectionId) -> Result { + let connect = Context::::new(); + ChannelReader::connection_end(&connect, connection_id) + } + + /// Returns the `ChannelsConnection` for the given identifier `conn_id`. + fn connection_channels( + &self, + conn_id: &ConnectionId, + ) -> Result, Ics04Error> { + let connect = Context::::new(); + connect.connection_channels(conn_id) + } + + fn client_state(&self, client_id: &ClientId) -> Result { + let connect = Context::::new(); + + ChannelReader::client_state(&connect, client_id) + } + + fn client_consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + let connect = Context::::new(); + ChannelReader::client_consensus_state(&connect, client_id, height) + } + + fn get_next_sequence_send( + &self, + port_channel_id: &(PortId, ChannelId), + ) -> Result { + let connect = Context::::new(); + connect.get_next_sequence_send(port_channel_id) + } + + fn get_next_sequence_recv( + &self, + port_channel_id: &(PortId, ChannelId), + ) -> Result { + let connect = Context::::new(); + connect.get_next_sequence_recv(port_channel_id) + } + + fn get_next_sequence_ack( + &self, + port_channel_id: &(PortId, ChannelId), + ) -> Result { + let connect = Context::::new(); + connect.get_next_sequence_ack(port_channel_id) + } + + /// Returns the `PacketCommitment` for the given identifier `(PortId, ChannelId, Sequence)`. + fn get_packet_commitment( + &self, + key: &(PortId, ChannelId, Sequence), + ) -> Result { + let connect = Context::::new(); + connect.get_packet_commitment(key) + } + + fn get_packet_receipt( + &self, + key: &(PortId, ChannelId, Sequence), + ) -> Result { + let connect = Context::::new(); + connect.get_packet_receipt(key) + } + + /// Returns the `Acknowledgements` for the given identifier `(PortId, ChannelId, Sequence)`. + fn get_packet_acknowledgement( + &self, + key: &(PortId, ChannelId, Sequence), + ) -> Result { + let connect = Context::::new(); + connect.get_packet_acknowledgement(key) + } + + /// A hashing function for packet commitments + fn hash(&self, value: Vec) -> Vec { + let connect = Context::::new(); + connect.hash(value) + } + + /// Returns the current height of the local chain. + fn host_height(&self) -> Height { + let connect = Context::::new(); + ChannelReader::host_height(&connect) + } + + /// Returns the current timestamp of the local chain. + fn host_timestamp(&self) -> Timestamp { + let connect = Context::::new(); + ChannelReader::host_timestamp(&connect) + } + + /// Returns the `AnyConsensusState` for the given identifier `height`. + fn host_consensus_state(&self, height: Height) -> Result { + let connect = Context::::new(); + ConnectionReader::host_consensus_state(&connect, height) + .map_err(Ics04Error::ics03_connection) + } + + fn pending_host_consensus_state(&self) -> Result { + let connect = Context::::new(); + ClientReader::pending_host_consensus_state(&connect) + .map_err(|e| Ics04Error::ics03_connection(ICS03Error::ics02_client(e))) + } + + /// Returns the `ClientProcessedTimes` for the given identifier `client_id` & `height`. + fn client_update_time( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + let connect = Context::::new(); + connect.client_update_time(client_id, height) + } + + fn client_update_height( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + let connect = Context::::new(); + connect.client_update_height(client_id, height) + } + + /// Returns a counter on the number of channel ids have been created thus far. + /// The value of this counter should increase only via method + /// `ChannelKeeper::increase_channel_counter`. + fn channel_counter(&self) -> Result { + let connect = Context::::new(); + connect.channel_counter() + } + + fn max_expected_time_per_block(&self) -> Duration { + let connect = Context::::new(); + connect.max_expected_time_per_block() + } +} + +impl ChannelKeeper for TransferModule { + fn store_packet_commitment( + &mut self, + key: (PortId, ChannelId, Sequence), + commitment: IbcPacketCommitment, + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.store_packet_commitment(key, commitment) + } + + fn delete_packet_commitment( + &mut self, + key: (PortId, ChannelId, Sequence), + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.delete_packet_commitment(key) + } + + fn store_packet_receipt( + &mut self, + key: (PortId, ChannelId, Sequence), + receipt: Receipt, + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.store_packet_receipt(key, receipt) + } + + fn store_packet_acknowledgement( + &mut self, + key: (PortId, ChannelId, Sequence), + ack_commitment: IbcAcknowledgementCommitment, + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + + connect.store_packet_acknowledgement(key, ack_commitment) + } + + fn delete_packet_acknowledgement( + &mut self, + key: (PortId, ChannelId, Sequence), + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.delete_packet_acknowledgement(key) + } + + fn store_connection_channels( + &mut self, + conn_id: ConnectionId, + port_channel_id: &(PortId, ChannelId), + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.store_connection_channels(conn_id, port_channel_id) + } + + /// Stores the given channel_end at a path associated with the port_id and channel_id. + fn store_channel( + &mut self, + port_channel_id: (PortId, ChannelId), + channel_end: &ChannelEnd, + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.store_channel(port_channel_id, channel_end) + } + + fn store_next_sequence_send( + &mut self, + port_channel_id: (PortId, ChannelId), + seq: Sequence, + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.store_next_sequence_send(port_channel_id, seq) + } + + fn store_next_sequence_recv( + &mut self, + port_channel_id: (PortId, ChannelId), + seq: Sequence, + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.store_next_sequence_recv(port_channel_id, seq) + } + + fn store_next_sequence_ack( + &mut self, + port_channel_id: (PortId, ChannelId), + seq: Sequence, + ) -> Result<(), Ics04Error> { + let mut connect = Context::::new(); + connect.store_next_sequence_ack(port_channel_id, seq) + } + + fn increase_channel_counter(&mut self) { + let mut connect = Context::::new(); + connect.increase_channel_counter() + } +} diff --git a/frame/ibc/src/module/applications/transfer/mod.rs b/frame/ibc/src/module/applications/transfer/mod.rs new file mode 100644 index 0000000000000..2c638c7f9d54f --- /dev/null +++ b/frame/ibc/src/module/applications/transfer/mod.rs @@ -0,0 +1,288 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 mod channel; +pub mod transfer_handle_callback; + +use crate::{context::Context, *}; +use frame_support::traits::{ + fungibles::{Mutate, Transfer}, + ExistenceRequirement::AllowDeath, +}; +use log::{error, trace}; + +use crate::utils::get_channel_escrow_address; +use ibc::{ + applications::transfer::{ + context::{BankKeeper, Ics20Context, Ics20Keeper, Ics20Reader}, + error::Error as Ics20Error, + PrefixedCoin, PORT_ID_STR, + }, + core::ics24_host::identifier::PortId, + signer::Signer, +}; +use sp_runtime::{ + traits::{CheckedConversion, IdentifyAccount, Verify}, + MultiSignature, +}; + +use transfer_handle_callback::TransferModule; + +impl Ics20Keeper for TransferModule { + type AccountId = ::AccountId; +} + +impl BankKeeper for TransferModule { + type AccountId = ::AccountId; + + fn send_coins( + &mut self, + from: &Self::AccountId, + to: &Self::AccountId, + amt: &PrefixedCoin, + ) -> Result<(), Ics20Error> { + // TODO(davirain): trace_path now is private + // let is_native_asset = amt.denom.trace_path().is_empty(); + let is_native_asset = true; + match is_native_asset { + // transfer native token + true => { + // TODO(davirain): amount now is private, and base_denom is private + // let amount = amt.amount.as_u256().low_u128().checked_into().expect("Convert MUST + // NOT Failed"); let ibc_token_name = amt.denom.base_denom().as_str().as_bytes(); + let amount = todo!(); + let ibc_token_name = &[1, 1, 2, 3]; + let native_token_name = T::NATIVE_TOKEN_NAME; + + // assert native token name equal want to send ibc token name + assert_eq!( + native_token_name, ibc_token_name, + "send ibc token name is not native token name" + ); + + >::transfer( + &from.clone().into_account(), + &to.clone().into_account(), + amount, + AllowDeath, + ) + .map_err(|error| { + error!("❌ [send_coins] : Error: ({:?})", error); + Ics20Error::invalid_token() + })?; + + // add emit transfer native token event + Pallet::::deposit_event(Event::::TransferNativeToken( + from.clone(), + to.clone(), + amount, + )) + }, + // transfer non-native token + false => { + // TODO(davirain): amount now is private, and base_denom is private + // let amount = amt.amount.as_u256().low_u128().into(); + // let denom = amt.denom.base_denom().as_str(); + let amount = todo!(); + let denom = &[1, 1, 2, 3]; + // look cross chain asset have register in host chain + match T::AssetIdByName::try_get_asset_id(denom) { + Ok(token_id) => { + >::transfer( + token_id.into(), + &from.clone().into_account(), + &to.clone().into_account(), + amount, + true, + ) + .map_err(|error| { + error!("❌ [send_coins] : Error: ({:?})", error); + Ics20Error::invalid_token() + })?; + + // add emit transfer no native token event + Pallet::::deposit_event(Event::::TransferNoNativeToken( + from.clone(), + to.clone(), + amount, + )); + }, + Err(_error) => { + error!("❌ [send_coins]: denom: ({:?})", denom); + return Err(Ics20Error::invalid_token()) + }, + } + }, + } + + Ok(()) + } + + fn mint_coins( + &mut self, + account: &Self::AccountId, + amt: &PrefixedCoin, + ) -> Result<(), Ics20Error> { + // TODO(davirain): amount now is private, and base_denom is private + // let amount = amt.amount.as_u256().low_u128().into(); + // let denom = amt.denom.base_denom().as_str(); + let amount = todo!(); + let denom = &[1, 1, 2, 3]; + // look cross chain asset have register in host chain + match T::AssetIdByName::try_get_asset_id(denom) { + Ok(token_id) => { + >::mint_into( + token_id.into(), + &account.clone().into_account(), + amount, + ) + .map_err(|error| { + error!("❌ [mint_coins] : Error: ({:?})", error); + Ics20Error::invalid_token() + })?; + + // add mint token event + Pallet::::deposit_event(Event::::MintToken( + token_id, + account.clone(), + amount, + )); + }, + Err(_error) => { + error!("❌ [mint_coins]: denom: ({:?})", denom); + return Err(Ics20Error::invalid_token()) + }, + } + Ok(()) + } + + fn burn_coins( + &mut self, + account: &Self::AccountId, + amt: &PrefixedCoin, + ) -> Result<(), Ics20Error> { + // TODO(davirain): amount now is private, and base_denom is private + // let amount = amt.amount.as_u256().low_u128().into(); + // let denom = amt.denom.base_denom().as_str(); + let amount = todo!(); + let denom = &[1, 1, 2, 3]; + // look cross chain asset have register in host chain + match T::AssetIdByName::try_get_asset_id(denom) { + Ok(token_id) => { + >::burn_from( + token_id.into(), + &account.clone().into_account(), + amount, + ) + .map_err(|error| { + error!("❌ [burn_coins] : Error: ({:?})", error); + Ics20Error::invalid_token() + })?; + + // add burn token event + Pallet::::deposit_event(Event::::BurnToken( + token_id, + account.clone(), + amount, + )); + }, + Err(_error) => { + error!("❌ [burn_coins]: denom: ({:?})", denom); + return Err(Ics20Error::invalid_token()) + }, + } + Ok(()) + } +} + +impl Ics20Reader for TransferModule { + type AccountId = ::AccountId; + + fn get_port(&self) -> Result { + PortId::from_str(PORT_ID_STR) + .map_err(|e| Ics20Error::invalid_port_id(PORT_ID_STR.to_string(), e)) + } + + fn get_channel_escrow_address( + &self, + port_id: &PortId, + channel_id: &IbcChannelId, + ) -> Result { + get_channel_escrow_address(port_id, channel_id)? + .try_into() + .map_err(|_| Ics20Error::parse_account_failure()) + } + + fn is_send_enabled(&self) -> bool { + // TODO(davirain), need according channelEnd def + true + } + + fn is_receive_enabled(&self) -> bool { + // TODO(davirain), need according channelEnd def + true + } +} + +impl Ics20Context for TransferModule { + type AccountId = ::AccountIdConversion; // Need Setting Account TODO(davirian) +} + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +#[derive(Clone, Debug, PartialEq, TypeInfo, Encode, Decode)] +pub struct IbcAccount(AccountId); + +impl IdentifyAccount for IbcAccount { + type AccountId = AccountId; + fn into_account(self) -> Self::AccountId { + self.0 + } +} + +impl TryFrom for IbcAccount +where + AccountId: From<[u8; 32]>, +{ + type Error = &'static str; + + /// Convert a signer to an IBC account. + /// Only valid hex strings are supported for now. + fn try_from(signer: Signer) -> Result { + let acc_str = signer.as_ref(); + if acc_str.starts_with("0x") { + match acc_str.strip_prefix("0x") { + Some(hex_string) => TryInto::<[u8; 32]>::try_into( + hex::decode(hex_string).map_err(|_| "Error decoding invalid hex string")?, + ) + .map_err(|_| "Invalid account id hex string") + .map(|acc| Self(acc.into())), + _ => Err("Signer does not hold a valid hex string"), + } + } + // Do SS58 decoding instead + else { + error!("Convert Signer ❌ : Failed! "); + Err("invalid ibc address or substrate address") + } + } +} diff --git a/frame/ibc/src/module/applications/transfer/transfer_handle_callback.rs b/frame/ibc/src/module/applications/transfer/transfer_handle_callback.rs new file mode 100644 index 0000000000000..4abf0f625bba4 --- /dev/null +++ b/frame/ibc/src/module/applications/transfer/transfer_handle_callback.rs @@ -0,0 +1,178 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::*; + +use crate::utils::host_height; +use ibc::{ + applications::transfer::{acknowledgement::Acknowledgement, error::Error as Ics20Error}, + core::{ + ics04_channel::{ + channel::{Counterparty, Order}, + context::ChannelKeeper, + error::Error as Ics04Error, + msgs::acknowledgement::Acknowledgement as GenericAcknowledgement, + packet::{Packet as IbcPacket, PacketResult}, + Version, + }, + ics24_host::identifier::{ChannelId as IbcChannelId, ConnectionId, PortId}, + ics26_routing::context::{Module, ModuleOutputBuilder, OnRecvPacketAck}, + }, + events::IbcEvent, + signer::Signer, +}; + +/// A structure handling ICS20 callback +#[derive(Debug)] +pub struct TransferModule(pub PhantomData); + +impl Module for TransferModule { + fn on_chan_open_init( + &mut self, + output: &mut ModuleOutputBuilder, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &IbcChannelId, + counterparty: &Counterparty, + version: &Version, + ) -> Result<(), Ics04Error> { + ibc::applications::transfer::context::on_chan_open_init( + self, + output, + order, + connection_hops, + port_id, + channel_id, + counterparty, + version, + ) + .map_err(|value| Ics04Error::app_module(value.to_string())) + } + + fn on_chan_open_try( + &mut self, + output: &mut ModuleOutputBuilder, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &IbcChannelId, + counterparty: &Counterparty, + version: &Version, + counterparty_version: &Version, + ) -> Result { + ibc::applications::transfer::context::on_chan_open_try( + self, + output, + order, + connection_hops, + port_id, + channel_id, + counterparty, + version, + counterparty_version, + ) + .map_err(|value| Ics04Error::app_module(value.to_string())) + } + + fn on_chan_open_ack( + &mut self, + output: &mut ModuleOutputBuilder, + port_id: &PortId, + channel_id: &IbcChannelId, + counterparty_version: &Version, + ) -> Result<(), Ics04Error> { + ibc::applications::transfer::context::on_chan_open_ack( + self, + output, + port_id, + channel_id, + counterparty_version, + ) + .map_err(|value| Ics04Error::app_module(value.to_string())) + } + + fn on_chan_open_confirm( + &mut self, + output: &mut ModuleOutputBuilder, + port_id: &PortId, + channel_id: &IbcChannelId, + ) -> Result<(), Ics04Error> { + ibc::applications::transfer::context::on_chan_open_confirm( + self, output, port_id, channel_id, + ) + .map_err(|value| Ics04Error::app_module(value.to_string())) + } + + fn on_chan_close_init( + &mut self, + output: &mut ModuleOutputBuilder, + port_id: &PortId, + channel_id: &IbcChannelId, + ) -> Result<(), Ics04Error> { + ibc::applications::transfer::context::on_chan_close_init(self, output, port_id, channel_id) + .map_err(|value| Ics04Error::app_module(value.to_string())) + } + + fn on_chan_close_confirm( + &mut self, + output: &mut ModuleOutputBuilder, + port_id: &PortId, + channel_id: &IbcChannelId, + ) -> Result<(), Ics04Error> { + ibc::applications::transfer::context::on_chan_close_confirm( + self, output, port_id, channel_id, + ) + .map_err(|value| Ics04Error::app_module(value.to_string())) + } + + fn on_recv_packet( + &self, + output: &mut ModuleOutputBuilder, + packet: &IbcPacket, + relayer: &Signer, + ) -> OnRecvPacketAck { + ibc::applications::transfer::context::on_recv_packet(self, output, packet, relayer) + } + + fn on_acknowledgement_packet( + &mut self, + output: &mut ModuleOutputBuilder, + packet: &IbcPacket, + acknowledgement: &GenericAcknowledgement, + relayer: &Signer, + ) -> Result<(), Ics04Error> { + ibc::applications::transfer::context::on_acknowledgement_packet( + self, + output, + packet, + acknowledgement, + relayer, + ) + .map_err(|value| Ics04Error::app_module(value.to_string())) + } + + fn on_timeout_packet( + &mut self, + output: &mut ModuleOutputBuilder, + packet: &IbcPacket, + relayer: &Signer, + ) -> Result<(), Ics04Error> { + ibc::applications::transfer::context::on_timeout_packet(self, output, packet, relayer) + .map_err(|value| Ics04Error::app_module(value.to_string())) + } +} diff --git a/frame/ibc/src/module/core/ics02_client.rs b/frame/ibc/src/module/core/ics02_client.rs new file mode 100644 index 0000000000000..e555dec03d738 --- /dev/null +++ b/frame/ibc/src/module/core/ics02_client.rs @@ -0,0 +1,252 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::*; +use alloc::string::ToString; +use core::str::FromStr; +use log::{error, info, trace, warn}; + +use crate::context::Context; +use ibc::{ + core::{ + ics02_client::{ + client_consensus::AnyConsensusState, + client_state::AnyClientState, + client_type::ClientType, + context::{ClientKeeper, ClientReader}, + error::Error as Ics02Error, + }, + ics24_host::{ + identifier::ClientId, + path::{ClientConsensusStatePath, ClientStatePath, ClientTypePath}, + }, + }, + timestamp::Timestamp, + Height, +}; + +impl ClientReader for Context { + fn client_type(&self, client_id: &ClientId) -> Result { + let client_type_path = ClientTypePath(client_id.clone()).to_string().as_bytes().to_vec(); + if >::contains_key(client_type_path.clone()) { + let data = >::get(client_type_path); + let data = + String::from_utf8(data).map_err(|_| Ics02Error::implementation_specific())?; + ClientType::from_str(&data).map_err(|e| Ics02Error::unknown_client_type(e.to_string())) + } else { + Err(Ics02Error::client_not_found(client_id.clone())) + } + } + + fn client_state(&self, client_id: &ClientId) -> Result { + let client_state_path = ClientStatePath(client_id.clone()).to_string().as_bytes().to_vec(); + + if >::contains_key(&client_state_path) { + let data = >::get(&client_state_path); + AnyClientState::decode_vec(&*data).map_err(|_| Ics02Error::implementation_specific()) + } else { + Err(Ics02Error::client_not_found(client_id.clone())) + } + } + + fn consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + // search key + let client_consensus_state_path = ClientConsensusStatePath { + client_id: client_id.clone(), + epoch: height.revision_number(), + height: height.revision_height(), + } + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(client_consensus_state_path.clone()) { + let values = >::get(client_consensus_state_path.clone()); + AnyConsensusState::decode_vec(&*values) + .map_err(|_| Ics02Error::implementation_specific()) + } else { + Err(Ics02Error::consensus_state_not_found(client_id.clone(), height)) + } + } + + fn next_consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result, Ics02Error> { + // search key + let client_consensus_state_path = ClientConsensusStatePath { + client_id: client_id.clone(), + epoch: height.revision_number(), + height: height.revision_height(), + } + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(client_consensus_state_path.clone()) { + let values = >::get(client_consensus_state_path.clone()); + let any_consensus_state = AnyConsensusState::decode_vec(&*values) + .map_err(|_| Ics02Error::implementation_specific())?; + Ok(Some(any_consensus_state)) + } else { + Err(Ics02Error::consensus_state_not_found(client_id.clone(), height)) + } + } + + fn prev_consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result, Ics02Error> { + // search key + let client_consensus_state_path = ClientConsensusStatePath { + client_id: client_id.clone(), + epoch: height.revision_number(), + height: height.revision_height(), + } + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(client_consensus_state_path.clone()) { + let values = >::get(client_consensus_state_path.clone()); + let any_consensus_state = AnyConsensusState::decode_vec(&*values).unwrap(); + Ok(Some(any_consensus_state)) + } else { + Err(Ics02Error::consensus_state_not_found(client_id.clone(), height)) + } + } + + fn host_height(&self) -> Height { + let block_number = format!("{:?}", >::block_number()); + let current_height: u64 = block_number.parse().unwrap_or_default(); + Height::new(REVISION_NUMBER, current_height).expect("Contruct Heigjt Never failed") + } + + fn host_consensus_state(&self, _height: Height) -> Result { + todo!() + } + + fn pending_host_consensus_state(&self) -> Result { + todo!() + } + + fn client_counter(&self) -> Result { + Ok(>::get()) + } +} + +impl ClientKeeper for Context { + fn store_client_type( + &mut self, + client_id: ClientId, + client_type: ClientType, + ) -> Result<(), Ics02Error> { + let client_type_path = ClientTypePath(client_id.clone()).to_string().as_bytes().to_vec(); + let client_type = client_type.as_str().encode(); + >::insert(client_type_path, client_type); + Ok(()) + } + + fn store_client_state( + &mut self, + client_id: ClientId, + client_state: AnyClientState, + ) -> Result<(), Ics02Error> { + let client_state_path = ClientStatePath(client_id.clone()).to_string().as_bytes().to_vec(); + + let data = client_state.encode_vec().map_err(|_| Ics02Error::implementation_specific())?; + // store client states key-value + >::insert(client_state_path.clone(), data); + + Ok(()) + } + + fn store_consensus_state( + &mut self, + client_id: ClientId, + height: Height, + consensus_state: AnyConsensusState, + ) -> Result<(), Ics02Error> { + // store key + let client_consensus_state_path = ClientConsensusStatePath { + client_id: client_id.clone(), + epoch: height.revision_number(), + height: height.revision_height(), + } + .to_string() + .as_bytes() + .to_vec(); + + // store value + let consensus_state = consensus_state + .encode_vec() + .map_err(|_| Ics02Error::implementation_specific())?; + // store client_consensus_state path as key, consensus_state as value + >::insert(client_consensus_state_path, consensus_state); + + Ok(()) + } + + fn increase_client_counter(&mut self) { + let ret = >::try_mutate(|val| -> Result<(), Ics02Error> { + let new = val.checked_add(1).expect("Never Overflow"); + *val = new; + Ok(()) + }); + } + + fn store_update_time( + &mut self, + client_id: ClientId, + height: Height, + timestamp: Timestamp, + ) -> Result<(), Ics02Error> { + let encode_timestamp = serde_json::to_string(×tamp) + .map_err(|_| Ics02Error::implementation_specific())? + .as_bytes() + .to_vec(); + + >::insert( + client_id.as_bytes(), + height.encode_vec().map_err(|_| Ics02Error::implementation_specific())?, + encode_timestamp, + ); + + Ok(()) + } + + fn store_update_height( + &mut self, + client_id: ClientId, + height: Height, + host_height: Height, + ) -> Result<(), Ics02Error> { + >::insert( + client_id.as_bytes(), + height.encode_vec().map_err(|_| Ics02Error::implementation_specific())?, + host_height.encode_vec().map_err(|_| Ics02Error::implementation_specific())?, + ); + + Ok(()) + } +} diff --git a/frame/ibc/src/module/core/ics03_connection.rs b/frame/ibc/src/module/core/ics03_connection.rs new file mode 100644 index 0000000000000..82a9803cfa972 --- /dev/null +++ b/frame/ibc/src/module/core/ics03_connection.rs @@ -0,0 +1,128 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::*; + +use crate::context::Context; +use log::{error, info, trace, warn}; + +use ibc::{ + core::{ + ics02_client::{ + client_consensus::AnyConsensusState, client_state::AnyClientState, + context::ClientReader, + }, + ics03_connection::{ + connection::ConnectionEnd, + context::{ConnectionKeeper, ConnectionReader}, + error::Error as Ics03Error, + }, + ics23_commitment::commitment::CommitmentPrefix, + ics24_host::{ + identifier::{ClientId, ConnectionId}, + path::{ClientConnectionsPath, ConnectionsPath}, + }, + }, + Height, +}; + +impl ConnectionReader for Context { + fn connection_end(&self, conn_id: &ConnectionId) -> Result { + let connections_path = ConnectionsPath(conn_id.clone()).to_string().as_bytes().to_vec(); + + if >::contains_key(&connections_path) { + let data = >::get(&connections_path); + ConnectionEnd::decode_vec(&*data).map_err(|_| Ics03Error::implementation_specific()) + } else { + Err(Ics03Error::connection_mismatch(conn_id.clone())) + } + } + + fn client_state(&self, client_id: &ClientId) -> Result { + ClientReader::client_state(self, client_id).map_err(Ics03Error::ics02_client) + } + + fn host_current_height(&self) -> Height { + let block_number = format!("{:?}", >::block_number()); + let current_height: u64 = block_number.parse().unwrap_or_default(); + >::put(current_height); + Height::new(REVISION_NUMBER, current_height).expect("Contruct Height Never faild") + } + + fn host_oldest_height(&self) -> Height { + let height = >::get(); + Height::new(REVISION_NUMBER, height).expect("get host oldest height Never faild") + } + + fn commitment_prefix(&self) -> CommitmentPrefix { + "ibc".as_bytes().to_vec().try_into().unwrap_or_default() + } + + fn client_consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + ClientReader::consensus_state(self, client_id, height).map_err(Ics03Error::ics02_client) + } + + fn host_consensus_state(&self, _height: Height) -> Result { + todo!() + } + + fn connection_counter(&self) -> Result { + Ok(>::get()) + } +} + +impl ConnectionKeeper for Context { + fn store_connection( + &mut self, + connection_id: ConnectionId, + connection_end: &ConnectionEnd, + ) -> Result<(), Ics03Error> { + let connections_path = + ConnectionsPath(connection_id.clone()).to_string().as_bytes().to_vec(); + let data = + connection_end.encode_vec().map_err(|_| Ics03Error::implementation_specific())?; + + // store connection end + >::insert(connections_path, data); + + Ok(()) + } + + fn store_connection_to_client( + &mut self, + connection_id: ConnectionId, + client_id: &ClientId, + ) -> Result<(), Ics03Error> { + let client_connection_paths = + ClientConnectionsPath(client_id.clone()).to_string().as_bytes().to_vec(); + + >::insert(client_connection_paths, connection_id.as_bytes().to_vec()); + Ok(()) + } + + fn increase_connection_counter(&mut self) { + let ret = >::try_mutate(|val| -> Result<(), Ics03Error> { + let new = val.checked_add(1).expect("Never Overflow"); + *val = new; + Ok(()) + }); + } +} diff --git a/frame/ibc/src/module/core/ics04_channel.rs b/frame/ibc/src/module/core/ics04_channel.rs new file mode 100644 index 0000000000000..b17a4a48dd6c4 --- /dev/null +++ b/frame/ibc/src/module/core/ics04_channel.rs @@ -0,0 +1,542 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::*; +use core::{str::FromStr, time::Duration}; +use log::{error, info, trace, warn}; + +use crate::context::Context; +use ibc::{ + core::{ + ics02_client::{ + client_consensus::AnyConsensusState, client_state::AnyClientState, + context::ClientReader, + }, + ics03_connection::{ + connection::ConnectionEnd, context::ConnectionReader, error::Error as ICS03Error, + }, + ics04_channel::{ + channel::ChannelEnd, + commitment::{ + AcknowledgementCommitment as IbcAcknowledgementCommitment, + PacketCommitment as IbcPacketCommitment, + }, + context::{ChannelKeeper, ChannelReader}, + error::Error as Ics04Error, + packet::{Receipt, Sequence}, + }, + ics05_port::{context::PortReader, error::Error as Ics05Error}, + ics24_host::{ + identifier::{ChannelId, ClientId, ConnectionId, PortId}, + path::{ + AcksPath, ChannelEndsPath, CommitmentsPath, ConnectionsPath, ReceiptsPath, + SeqAcksPath, SeqRecvsPath, SeqSendsPath, + }, + Path, + }, + ics26_routing::context::ModuleId, + }, + timestamp::Timestamp, + Height, +}; + +impl ChannelReader for Context { + fn channel_end(&self, port_channel_id: &(PortId, ChannelId)) -> Result { + let channel_end_path = + ChannelEndsPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + + let data = >::get(channel_end_path); + + ChannelEnd::decode_vec(&*data).map_err(|_| { + Ics04Error::channel_not_found(port_channel_id.clone().0, port_channel_id.clone().1) + }) + } + + fn connection_end(&self, connection_id: &ConnectionId) -> Result { + ConnectionReader::connection_end(self, connection_id).map_err(Ics04Error::ics03_connection) + } + + /// Returns the `ChannelsConnection` for the given identifier `conn_id`. + fn connection_channels( + &self, + conn_id: &ConnectionId, + ) -> Result, Ics04Error> { + // store key + let connections_path = ConnectionsPath(conn_id.clone()).to_string().as_bytes().to_vec(); + + if >::contains_key(&connections_path) { + let channel_ends_paths = >::get(&connections_path); + + let mut result = vec![]; + + for item in channel_ends_paths.into_iter() { + let raw_path = + String::from_utf8(item).map_err(|_| Ics04Error::implementation_specific())?; + // decode key + let path = + Path::from_str(&raw_path).map_err(|_| Ics04Error::implementation_specific())?; + + if let Path::ChannelEnds(channel_ends_path) = path { + let ChannelEndsPath(port_id, channel_id) = channel_ends_path; + result.push((port_id, channel_id)); + } + } + + Ok(result) + } else { + Err(Ics04Error::connection_not_open(conn_id.clone())) + } + } + + fn client_state(&self, client_id: &ClientId) -> Result { + ClientReader::client_state(self, client_id) + .map_err(|_| Ics04Error::implementation_specific()) + } + + fn client_consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + ClientReader::consensus_state(self, client_id, height) + .map_err(|_| Ics04Error::implementation_specific()) + } + + fn get_next_sequence_send( + &self, + port_channel_id: &(PortId, ChannelId), + ) -> Result { + let seq_sends_path = SeqSendsPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(&seq_sends_path) { + let sequence = >::get(&seq_sends_path); + Ok(Sequence::from(sequence)) + } else { + Err(Ics04Error::missing_next_send_seq(port_channel_id.clone())) + } + } + + fn get_next_sequence_recv( + &self, + port_channel_id: &(PortId, ChannelId), + ) -> Result { + let seq_recvs_path = SeqRecvsPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(&seq_recvs_path) { + let sequence = >::get(&seq_recvs_path); + + Ok(Sequence::from(sequence)) + } else { + Err(Ics04Error::missing_next_recv_seq(port_channel_id.clone())) + } + } + + fn get_next_sequence_ack( + &self, + port_channel_id: &(PortId, ChannelId), + ) -> Result { + let seq_acks_path = SeqAcksPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(&seq_acks_path) { + let sequence = >::get(&seq_acks_path); + + Ok(Sequence::from(sequence)) + } else { + Err(Ics04Error::missing_next_ack_seq(port_channel_id.clone())) + } + } + + /// Returns the `PacketCommitment` for the given identifier `(PortId, ChannelId, Sequence)`. + fn get_packet_commitment( + &self, + key: &(PortId, ChannelId, Sequence), + ) -> Result { + let packet_commitments_path = CommitmentsPath { + port_id: key.0.clone(), + channel_id: key.1.clone(), + sequence: key.2.clone(), + } + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(&packet_commitments_path) { + let data = >::get(&packet_commitments_path); + + let packet_commitment = IbcPacketCommitment::from(data); + + Ok(packet_commitment) + } else { + Err(Ics04Error::packet_commitment_not_found(key.2)) + } + } + + fn get_packet_receipt( + &self, + key: &(PortId, ChannelId, Sequence), + ) -> Result { + let packet_receipt_path = ReceiptsPath { + port_id: key.0.clone(), + channel_id: key.1.clone(), + sequence: key.2.clone(), + } + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(&packet_receipt_path) { + let data = >::get(&packet_receipt_path); + let data = + String::from_utf8(data).map_err(|_| Ics04Error::implementation_specific())?; + let data = match data.as_ref() { + "Ok" => Receipt::Ok, + _ => unreachable!(), + }; + Ok(data) + } else { + Err(Ics04Error::packet_receipt_not_found(key.2)) + } + } + + /// Returns the `Acknowledgements` for the given identifier `(PortId, ChannelId, Sequence)`. + fn get_packet_acknowledgement( + &self, + key: &(PortId, ChannelId, Sequence), + ) -> Result { + let acks_path = + AcksPath { port_id: key.0.clone(), channel_id: key.1.clone(), sequence: key.2.clone() } + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(&acks_path) { + let data = >::get(&acks_path); + + let acknowledgement = IbcAcknowledgementCommitment::from(data); + Ok(acknowledgement) + } else { + Err(Ics04Error::packet_acknowledgement_not_found(key.2)) + } + } + + /// A hashing function for packet commitments + fn hash(&self, value: Vec) -> Vec { + sp_io::hashing::sha2_256(&value).to_vec() + } + + /// Returns the current height of the local chain. + fn host_height(&self) -> Height { + //todo this can improve + let block_number = format!("{:?}", >::block_number()); + let current_height: u64 = block_number.parse().unwrap_or_default(); + + Height::new(REVISION_NUMBER, current_height).expect("Contruct Height Never Faild") + } + + /// Returns the current timestamp of the local chain. + fn host_timestamp(&self) -> Timestamp { + use frame_support::traits::UnixTime; + let time = T::TimeProvider::now(); + + Timestamp::from_nanoseconds(time.as_nanos() as u64).expect("Convert Timestamp Never Faild") + } + + /// Returns the `AnyConsensusState` for the given identifier `height`. + fn host_consensus_state(&self, height: Height) -> Result { + ConnectionReader::host_consensus_state(self, height).map_err(Ics04Error::ics03_connection) + } + + fn pending_host_consensus_state(&self) -> Result { + ClientReader::pending_host_consensus_state(self) + .map_err(|e| Ics04Error::ics03_connection(ICS03Error::ics02_client(e))) + } + + /// Returns the `ClientProcessedTimes` for the given identifier `client_id` & `height`. + fn client_update_time( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + if >::contains_key( + client_id.as_bytes(), + height.encode_vec().map_err(|_| Ics04Error::implementation_specific())?, + ) { + let time = >::get( + client_id.as_bytes(), + height.encode_vec().map_err(|_| Ics04Error::implementation_specific())?, + ); + let timestamp = + String::from_utf8(time).map_err(|_| Ics04Error::implementation_specific())?; + let time: Timestamp = serde_json::from_str(×tamp) + .map_err(|_| Ics04Error::implementation_specific())?; + Ok(time) + } else { + Err(Ics04Error::processed_time_not_found(client_id.clone(), height)) + } + } + + fn client_update_height( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + if >::contains_key( + client_id.as_bytes(), + height.encode_vec().map_err(|_| Ics04Error::implementation_specific())?, + ) { + let host_height = >::get( + client_id.as_bytes(), + height.encode_vec().map_err(|_| Ics04Error::implementation_specific())?, + ); + Height::decode(&mut &host_height[..]).map_err(|_| Ics04Error::implementation_specific()) + } else { + Err(Ics04Error::processed_height_not_found(client_id.clone(), height)) + } + } + + /// Returns a counter on the number of channel ids have been created thus far. + /// The value of this counter should increase only via method + /// `ChannelKeeper::increase_channel_counter`. + fn channel_counter(&self) -> Result { + Ok( as Store>::ChannelCounter::get()) + } + + fn max_expected_time_per_block(&self) -> Duration { + Duration::from_secs(6) + } +} + +impl ChannelKeeper for Context { + fn store_packet_commitment( + &mut self, + key: (PortId, ChannelId, Sequence), + commitment: IbcPacketCommitment, + ) -> Result<(), Ics04Error> { + let packet_commitments_path = CommitmentsPath { + port_id: key.0.clone(), + channel_id: key.1.clone(), + sequence: key.2.clone(), + } + .to_string() + .as_bytes() + .to_vec(); + + // insert packet commitment key-value + >::insert(packet_commitments_path, commitment.into_vec()); + + Ok(()) + } + + fn delete_packet_commitment( + &mut self, + key: (PortId, ChannelId, Sequence), + ) -> Result<(), Ics04Error> { + let packet_commitments_path = CommitmentsPath { + port_id: key.0.clone(), + channel_id: key.1.clone(), + sequence: key.2.clone(), + } + .to_string() + .as_bytes() + .to_vec(); + + // delete packet commitment + >::remove(&packet_commitments_path); + + Ok(()) + } + + fn store_packet_receipt( + &mut self, + key: (PortId, ChannelId, Sequence), + receipt: Receipt, + ) -> Result<(), Ics04Error> { + let packet_receipt_path = ReceiptsPath { + port_id: key.0.clone(), + channel_id: key.1.clone(), + sequence: key.2.clone(), + } + .to_string() + .as_bytes() + .to_vec(); + + let receipt = match receipt { + Receipt::Ok => "Ok".as_bytes().to_vec(), + }; + + >::insert(packet_receipt_path, receipt); + + Ok(()) + } + + fn store_packet_acknowledgement( + &mut self, + key: (PortId, ChannelId, Sequence), + ack_commitment: IbcAcknowledgementCommitment, + ) -> Result<(), Ics04Error> { + let acks_path = + AcksPath { port_id: key.0.clone(), channel_id: key.1.clone(), sequence: key.2.clone() } + .to_string() + .as_bytes() + .to_vec(); + + // store packet acknowledgement key-value + >::insert(&acks_path, ack_commitment.into_vec()); + + Ok(()) + } + + fn delete_packet_acknowledgement( + &mut self, + key: (PortId, ChannelId, Sequence), + ) -> Result<(), Ics04Error> { + let acks_path = + AcksPath { port_id: key.0.clone(), channel_id: key.1.clone(), sequence: key.2.clone() } + .to_string() + .as_bytes() + .to_vec(); + + // remove acknowledgements + >::remove(&acks_path); + + Ok(()) + } + + fn store_connection_channels( + &mut self, + conn_id: ConnectionId, + port_channel_id: &(PortId, ChannelId), + ) -> Result<(), Ics04Error> { + // store key + let connections_path = ConnectionsPath(conn_id.clone()).to_string().as_bytes().to_vec(); + + // store value + let channel_ends_path = + ChannelEndsPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + + if >::contains_key(&connections_path) { + // if connection_id exist + >::try_mutate( + &connections_path, + |val| -> Result<(), Ics04Error> { + val.push(channel_ends_path.clone()); + Ok(()) + }, + ) + .expect("channels Connection mutate Error") + } else { + >::insert(connections_path, vec![channel_ends_path]); + } + + Ok(()) + } + + /// Stores the given channel_end at a path associated with the port_id and channel_id. + fn store_channel( + &mut self, + port_channel_id: (PortId, ChannelId), + channel_end: &ChannelEnd, + ) -> Result<(), Ics04Error> { + let channel_end_path = + ChannelEndsPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + let channel_end = + channel_end.encode_vec().map_err(|_| Ics04Error::implementation_specific())?; + + // store channels key-value + >::insert(channel_end_path, channel_end); + + Ok(()) + } + + fn store_next_sequence_send( + &mut self, + port_channel_id: (PortId, ChannelId), + seq: Sequence, + ) -> Result<(), Ics04Error> { + let seq_sends_path = SeqSendsPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + + let sequence = u64::from(seq); + + >::insert(seq_sends_path, sequence); + + Ok(()) + } + + fn store_next_sequence_recv( + &mut self, + port_channel_id: (PortId, ChannelId), + seq: Sequence, + ) -> Result<(), Ics04Error> { + let seq_recvs_path = SeqRecvsPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + let sequence = u64::from(seq); + + >::insert(seq_recvs_path, sequence); + + Ok(()) + } + + fn store_next_sequence_ack( + &mut self, + port_channel_id: (PortId, ChannelId), + seq: Sequence, + ) -> Result<(), Ics04Error> { + let seq_acks_path = SeqAcksPath(port_channel_id.0.clone(), port_channel_id.1.clone()) + .to_string() + .as_bytes() + .to_vec(); + let sequence = u64::from(seq); + + >::insert(seq_acks_path, sequence); + + Ok(()) + } + + /// Called upon channel identifier creation (Init or Try message processing). + /// Increases the counter which keeps track of how many channels have been created. + /// Should never fail. + fn increase_channel_counter(&mut self) { + let ret = >::try_mutate(|val| -> Result<(), Ics04Error> { + let new = val.checked_add(1).expect("Never Overflow"); + *val = new; + Ok(()) + }); + } +} diff --git a/frame/ibc/src/module/core/ics05_port.rs b/frame/ibc/src/module/core/ics05_port.rs new file mode 100644 index 0000000000000..5ac325bbb6ed8 --- /dev/null +++ b/frame/ibc/src/module/core/ics05_port.rs @@ -0,0 +1,41 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::*; +use log::trace; + +use crate::context::Context; +use ibc::{ + applications::transfer::{ + MODULE_ID_STR as TRANSFER_MODULE_ID, PORT_ID_STR as TRANSFER_PORT_ID, + }, + core::{ + ics05_port::{context::PortReader, error::Error as ICS05Error}, + ics24_host::identifier::PortId, + ics26_routing::context::ModuleId, + }, +}; + +impl PortReader for Context { + fn lookup_module_by_port(&self, port_id: &PortId) -> Result { + match port_id.as_str() { + TRANSFER_PORT_ID => Ok(ModuleId::from_str(TRANSFER_MODULE_ID) + .map_err(|_| ICS05Error::module_not_found(port_id.clone()))?), + _ => Err(ICS05Error::module_not_found(port_id.clone())), + } + } +} diff --git a/frame/ibc/src/module/core/ics24_host.rs b/frame/ibc/src/module/core/ics24_host.rs new file mode 100644 index 0000000000000..6d08244f1f1e8 --- /dev/null +++ b/frame/ibc/src/module/core/ics24_host.rs @@ -0,0 +1,272 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::{alloc::string::ToString, from_channel_id_to_vec, Config, Event, REVISION_NUMBER}; +use alloc::string::String; +use ibc::{ + core::{ + ics02_client::{client_type::ClientType as IbcClientType, height::Height as IbcHeight}, + ics04_channel::packet::{Packet as IbcPacket, Sequence as IbcSequence}, + ics24_host::{ + error::ValidationError, + identifier::{ + ChainId as IbcChainId, ChannelId as IbcChannelId, ClientId as IbcClientId, + ConnectionId as IbcConnectionId, PortId as IbcPortId, + }, + }, + }, + timestamp::Timestamp as IbcTimestamp, +}; +use sp_std::{str::FromStr, vec::Vec}; + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +use sp_runtime::RuntimeDebug; + +use flex_error::{define_error, DisplayOnly, TraceError}; +use ibc::core::ics04_channel::timeout::TimeoutHeight; +use tendermint_proto::Error as TendermintError; + +define_error! { + #[derive(Debug, PartialEq, Eq)] + Error { + InvalidFromUtf8 + [DisplayOnly] + | _ | { "invalid from utf8 error" }, + InvalidDecode + [DisplayOnly] + | _ | { "invalid decode error" }, + ParseTimestampFailed + [DisplayOnly] + | _ | { "invalid parse timestamp error" }, + ValidationFailed + [DisplayOnly] + | _ | { "invalid validation error"}, + InvalidChainId + [DisplayOnly] + |_| { "invalid chain id error" }, + } +} + +/// ibc-rs' `PortId` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct PortId(pub Vec); + +impl From for PortId { + fn from(value: IbcPortId) -> Self { + let value = value.as_str().as_bytes().to_vec(); + Self(value) + } +} + +impl From for IbcPortId { + fn from(value: PortId) -> Self { + let value = String::from_utf8(value.0).expect("convert Never faild"); + IbcPortId::from_str(&value).expect("convert Never faild") + } +} + +/// ibc-rs' `ChannelId` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ChannelId(pub Vec); + +impl From for ChannelId { + fn from(value: IbcChannelId) -> Self { + let value = from_channel_id_to_vec(value); + Self(value) + } +} + +impl From for IbcChannelId { + fn from(value: ChannelId) -> Self { + let value = String::from_utf8(value.0).expect("convert Never faild"); + Self::from_str(&value).expect("convert Never faild") + } +} + +/// ibc-rs' `Height` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct Height { + /// Previously known as "epoch" + pub revision_number: u64, + + /// The height of a block + pub revision_height: u64, +} + +impl From for Height { + fn from(ibc_height: IbcHeight) -> Self { + Height::new(ibc_height.revision_number(), ibc_height.revision_height()) + } +} + +impl From for IbcHeight { + fn from(height: Height) -> Self { + IbcHeight::new(REVISION_NUMBER, height.revision_height) + .expect("Contruct IbcHeight Never faild") + } +} + +impl Height { + pub fn new(revision_number: u64, revision_height: u64) -> Self { + Self { revision_number, revision_height } + } +} + +/// ibc-rs' `ClientType` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub enum ClientType { + Tendermint, + Grandpa, +} + +impl From for ClientType { + fn from(value: IbcClientType) -> Self { + match value { + IbcClientType::Tendermint => ClientType::Tendermint, + _ => unreachable!(), + } + } +} + +impl ClientType { + pub fn to_ibc_client_type(self) -> IbcClientType { + match self { + ClientType::Tendermint => IbcClientType::Tendermint, + _ => unreachable!(), + } + } +} + +/// ibc-rs' `ClientId` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ClientId(pub Vec); + +impl From for ClientId { + fn from(value: IbcClientId) -> Self { + let value = value.as_str().as_bytes().to_vec(); + Self(value) + } +} + +impl From for IbcClientId { + fn from(value: ClientId) -> Self { + let value = String::from_utf8(value.0).expect("convert Never faild"); + IbcClientId::from_str(&value).expect("convert Never faild") + } +} + +/// ibc-rs' `ConnectionId` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ConnectionId(pub Vec); + +impl From for ConnectionId { + fn from(value: IbcConnectionId) -> Self { + let value = value.as_str().as_bytes().to_vec(); + Self(value) + } +} + +impl From for IbcConnectionId { + fn from(value: ConnectionId) -> Self { + let value = String::from_utf8(value.0).expect("convert Never faild"); + IbcConnectionId::from_str(&value).expect("convert Never faild") + } +} + +/// ibc-rs' `Timestamp` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct Timestamp { + pub time: Vec, +} + +impl From for Timestamp { + fn from(val: IbcTimestamp) -> Self { + Self { time: val.nanoseconds().to_string().as_bytes().to_vec() } + } +} + +impl From for IbcTimestamp { + fn from(value: Timestamp) -> Self { + let value = String::from_utf8(value.time).expect("convert Never faild"); + Self::from_str(&value).expect("convert Never faild") + } +} + +/// ibc-rs' `Sequence` representation in substrate + +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct Sequence(u64); + +impl From for Sequence { + fn from(val: IbcSequence) -> Self { + Self(u64::from(val)) + } +} + +impl From for IbcSequence { + fn from(val: Sequence) -> Self { + IbcSequence::from(val.0) + } +} + +/// ibc-rs' `Packet` representation in substrate +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct Packet { + pub sequence: Sequence, + pub source_port: PortId, + pub source_channel: ChannelId, + pub destination_port: PortId, + pub destination_channel: ChannelId, + pub data: Vec, + pub timeout_height: Height, + pub timeout_timestamp: Timestamp, +} + +impl From for Packet { + fn from(val: IbcPacket) -> Self { + Self { + sequence: val.sequence.into(), + source_port: val.source_port.into(), + source_channel: val.source_channel.into(), + destination_port: val.destination_port.into(), + destination_channel: val.destination_channel.into(), + data: val.data, + timeout_height: match val.timeout_height { + TimeoutHeight::Never => Height::new(REVISION_NUMBER, u64::MAX), + TimeoutHeight::At(value) => value.into(), + }, + timeout_timestamp: val.timeout_timestamp.into(), + } + } +} + +impl From for IbcPacket { + fn from(value: Packet) -> Self { + Self { + sequence: value.sequence.into(), + source_port: value.source_port.into(), + source_channel: value.source_channel.into(), + destination_port: value.destination_port.into(), + destination_channel: value.destination_channel.into(), + data: value.data, + timeout_height: TimeoutHeight::At(value.timeout_height.into()), + timeout_timestamp: value.timeout_timestamp.into(), + } + } +} diff --git a/frame/ibc/src/module/core/ics26_routing.rs b/frame/ibc/src/module/core/ics26_routing.rs new file mode 100644 index 0000000000000..fedfeba33e675 --- /dev/null +++ b/frame/ibc/src/module/core/ics26_routing.rs @@ -0,0 +1,82 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::{context::Context, *}; +use alloc::{ + borrow::{Borrow, Cow, ToOwned}, + collections::BTreeMap, + fmt::format, + sync::Arc, +}; +use core::fmt::Formatter; +use ibc::core::ics26_routing::context::{Ics26Context, Module, ModuleId, RouterBuilder}; +use log::{error, info, trace, warn}; +use scale_info::TypeInfo; + +#[derive(Default)] +pub struct SubRouterBuilder(Router); + +impl RouterBuilder for SubRouterBuilder { + type Router = Router; + + fn add_route(mut self, module_id: ModuleId, module: impl Module) -> Result { + match self.0 .0.insert(module_id, Arc::new(module)) { + None => Ok(self), + Some(_) => Err("Duplicate module_id".to_owned()), + } + } + + fn build(self) -> Self::Router { + self.0 + } +} + +#[derive(Default, Clone)] +pub struct Router(BTreeMap>); + +impl Debug for Router { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + let mut keys = vec![]; + for (key, _) in self.0.iter() { + keys.push(format!("{}", key)); + } + + write!(f, "MockRouter(BTreeMap(key({:?})", keys.join(",")) + } +} + +impl ibc::core::ics26_routing::context::Router for Router { + fn get_route_mut(&mut self, module_id: &impl Borrow) -> Option<&mut dyn Module> { + self.0.get_mut(module_id.borrow()).and_then(Arc::get_mut) + } + + fn has_route(&self, module_id: &impl Borrow) -> bool { + self.0.get(module_id.borrow()).is_some() + } +} + +impl Ics26Context for Context { + type Router = Router; + + fn router(&self) -> &Self::Router { + &self.router + } + + fn router_mut(&mut self) -> &mut Self::Router { + &mut self.router + } +} diff --git a/frame/ibc/src/module/core/mod.rs b/frame/ibc/src/module/core/mod.rs new file mode 100644 index 0000000000000..9b9d7c270089d --- /dev/null +++ b/frame/ibc/src/module/core/mod.rs @@ -0,0 +1,23 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 mod ics02_client; +pub mod ics03_connection; +pub mod ics04_channel; +pub mod ics05_port; +pub mod ics24_host; +pub mod ics26_routing; diff --git a/frame/ibc/src/module/mod.rs b/frame/ibc/src/module/mod.rs new file mode 100644 index 0000000000000..d475ce0d9fff3 --- /dev/null +++ b/frame/ibc/src/module/mod.rs @@ -0,0 +1,20 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 mod applications; +pub mod core; +pub mod relayer; diff --git a/frame/ibc/src/module/relayer/mod.rs b/frame/ibc/src/module/relayer/mod.rs new file mode 100644 index 0000000000000..3f18d85aa2537 --- /dev/null +++ b/frame/ibc/src/module/relayer/mod.rs @@ -0,0 +1,64 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::{ + alloc::string::ToString, context::Context, utils::host_height, Config, REVISION_NUMBER, +}; +use ibc::{ + core::{ + ics02_client::{client_state::AnyClientState, context::ClientReader, header::AnyHeader}, + ics24_host::identifier::ClientId, + ics26_routing::handler::{deliver, MsgReceipt}, + }, + events::IbcEvent, + relayer::ics18_relayer::{context::Ics18Context, error::Error as ICS18Error}, + signer::Signer, + Height, +}; +use ibc_proto::google::protobuf::Any; +use scale_info::prelude::{vec, vec::Vec}; + +impl Ics18Context for Context { + fn query_latest_height(&self) -> Height { + let revision_height = host_height::(); + Height::new(REVISION_NUMBER, revision_height).expect(&REVISION_NUMBER.to_string()) + } + + fn query_client_full_state(&self, client_id: &ClientId) -> Option { + // Forward call to Ics2. + ClientReader::client_state(self, client_id).ok() + } + + fn query_latest_header(&self) -> Option { + todo!() + } + + fn send(&mut self, msgs: Vec) -> Result, ICS18Error> { + // Forward call to Ics26 delivery method. + let mut all_events = vec![]; + for msg in msgs { + let MsgReceipt { mut events, .. } = + deliver(self, msg).map_err(ICS18Error::transaction_failed)?; + all_events.append(&mut events); + } + Ok(all_events) + } + + fn signer(&self) -> Signer { + "0CDA3F47EF3C4906693B170EF650EB968C5F4B2C".parse().unwrap() + } +} diff --git a/frame/ibc/src/tests.rs b/frame/ibc/src/tests.rs new file mode 100644 index 0000000000000..1a30744f43137 --- /dev/null +++ b/frame/ibc/src/tests.rs @@ -0,0 +1,430 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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. + +//! Tests for the ibc pallet. +use super::*; +use crate::{mock::*, Context}; +use core::str::FromStr; + +use ibc::{ + applications::transfer::{context::Ics20Context, error::Error as ICS20Error}, + core::{ + ics02_client::{ + client_consensus::AnyConsensusState, + client_state::AnyClientState, + client_type::ClientType, + context::{ClientKeeper, ClientReader}, + error::Error as ICS02Error, + }, + ics03_connection::{ + connection::{ConnectionEnd, State}, + context::{ConnectionKeeper, ConnectionReader}, + error::Error as ICS03Error, + }, + ics04_channel::{ + channel::ChannelEnd, + context::{ChannelKeeper, ChannelReader}, + error::Error as ICS04Error, + packet::Sequence, + }, + ics23_commitment::commitment::CommitmentRoot, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, + }, + timestamp::Timestamp, + Height, +}; + +// test store and read client-type +#[test] +fn test_store_client_type_ok() { + let gp_client_type = ClientType::Tendermint; + let gp_client_id = ClientId::default(); + + let mut context: Context = Context::new(); + + new_test_ext().execute_with(|| { + assert!(context.store_client_type(gp_client_id.clone(), gp_client_type).is_ok()); + }) +} + +#[test] +fn test_read_client_type_failed_by_supply_error_client_id() { + let gp_client_type = ClientType::Tendermint; + let gp_client_id = ClientId::new(gp_client_type, 0).unwrap(); + let gp_client_id_failed = ClientId::new(gp_client_type, 1).unwrap(); + let mut context: Context = Context::new(); + + new_test_ext().execute_with(|| { + assert!(context.store_client_type(gp_client_id.clone(), gp_client_type).is_ok()); + + let ret = context.client_type(&gp_client_id_failed).unwrap_err().to_string(); + + assert_eq!(ret, ICS02Error::client_not_found(gp_client_id_failed).to_string()); + }) +} +#[test] +fn test_get_packet_commitment_state_ok() { + use ibc::core::ics04_channel::commitment::PacketCommitment; + + let mut context: Context = Context::new(); + + let range = (0..10).into_iter().collect::>(); + + let mut port_id_vec = vec![]; + let mut channel_id_vec = vec![]; + let mut sequence_vec = vec![]; + + for index in range.clone() { + port_id_vec.push(PortId::default()); + channel_id_vec.push(ChannelId::default()); + let sequence = Sequence::from(index as u64); + sequence_vec.push(sequence); + } + let com = PacketCommitment::from(vec![1, 2, 3]); + + new_test_ext().execute_with(|| { + for index in 0..range.len() { + assert!(context + .store_packet_commitment( + ( + port_id_vec[index].clone(), + channel_id_vec[index].clone(), + sequence_vec[index] + ), + com.clone(), + ) + .is_ok()); + } + }) +} + +#[test] +fn test_connection_ok() { + use codec::alloc::collections::HashMap; + + let mut input: HashMap = HashMap::new(); + + let connection_id0 = ConnectionId::default(); + let connection_end0 = ConnectionEnd::default(); + + let connection_id1 = ConnectionId::default(); + let connection_end1 = ConnectionEnd::default(); + + let connection_id2 = ConnectionId::default(); + let connection_end2 = ConnectionEnd::default(); + + input.insert(connection_id0.clone(), connection_end0.clone()); + input.insert(connection_id1.clone(), connection_end1.clone()); + input.insert(connection_id2.clone(), connection_end2.clone()); + + let mut context: Context = Context::new(); + new_test_ext().execute_with(|| { + assert_eq!( + ConnectionKeeper::store_connection( + &mut context, + connection_id0.clone(), + input.get(&connection_id0.clone()).unwrap() + ) + .is_ok(), + true + ); + + let ret = ConnectionReader::connection_end(&mut context, &connection_id0).unwrap(); + assert_eq!(ret, *input.get(&connection_id0.clone()).unwrap()); + + assert_eq!( + ConnectionKeeper::store_connection( + &mut context, + connection_id1.clone(), + input.get(&connection_id1.clone()).unwrap() + ) + .is_ok(), + true + ); + + assert_eq!( + ConnectionKeeper::store_connection( + &mut context, + connection_id2.clone(), + input.get(&connection_id2.clone()).unwrap() + ) + .is_ok(), + true + ); + }) +} + +#[test] +fn test_connection_fail() { + let connection_id0 = ConnectionId::default(); + let context: Context = Context::new(); + new_test_ext().execute_with(|| { + let ret = ConnectionReader::connection_end(&context, &connection_id0.clone()) + .unwrap_err() + .to_string(); + assert_eq!(ret, ICS03Error::connection_mismatch(connection_id0).to_string()); + }) +} + +#[test] +fn test_connection_client_ok() { + let gp_client_id = ClientId::default(); + let connection_id = ConnectionId::new(0); + let mut context: Context = Context::new(); + + new_test_ext().execute_with(|| { + assert!(context.store_connection_to_client(connection_id, &gp_client_id).is_ok()); + }) +} + +#[test] +fn test_delete_packet_acknowledgement_ok() { + use ibc::core::ics04_channel::commitment::AcknowledgementCommitment; + + let port_id = PortId::default(); + let channel_id = ChannelId::default(); + let sequence = Sequence::from(0); + let ack = AcknowledgementCommitment::from(vec![1, 2, 3]); + + let mut context: Context = Context::new(); + + new_test_ext().execute_with(|| { + assert!(context + .store_packet_acknowledgement( + (port_id.clone(), channel_id.clone(), sequence), + ack.clone() + ) + .is_ok()); + + assert!(context + .delete_packet_acknowledgement((port_id.clone(), channel_id.clone(), sequence)) + .is_ok()); + + let result = context + .get_packet_acknowledgement(&(port_id, channel_id, sequence)) + .unwrap_err() + .to_string(); + + assert_eq!(result, ICS04Error::packet_acknowledgement_not_found(sequence).to_string()); + }) +} + +#[test] +fn test_get_acknowledge_state() { + use ibc::core::ics04_channel::commitment::AcknowledgementCommitment; + let range = (0..10).into_iter().collect::>(); + + let mut port_id_vec = vec![]; + let mut channel_id_vec = vec![]; + let mut sequence_vec = vec![]; + let mut ack_vec = vec![]; + + let mut value_vec = vec![]; + + let mut context: Context = Context::new(); + + for index in 0..range.len() { + port_id_vec.push(PortId::default()); + channel_id_vec.push(ChannelId::default()); + let sequence = Sequence::from(index as u64); + sequence_vec.push(sequence); + ack_vec.push(AcknowledgementCommitment::from(vec![index as u8])); + value_vec.push(ChannelReader::hash(&context, vec![index as u8]).encode()); + } + + new_test_ext().execute_with(|| { + for index in 0..range.len() { + assert!(context + .store_packet_acknowledgement( + ( + port_id_vec[index].clone(), + channel_id_vec[index].clone(), + sequence_vec[index] + ), + ack_vec[index].clone() + ) + .is_ok()); + } + }) +} + +#[test] +fn test_store_connection_channles_ok() { + let connection_id = ConnectionId::default(); + let port_id = PortId::default(); + let channel_id = ChannelId::default(); + + let mut context: Context = Context::new(); + new_test_ext().execute_with(|| { + assert!(context + .store_connection_channels( + connection_id.clone(), + &(port_id.clone(), channel_id.clone()) + ) + .is_ok()); + + let result = context.connection_channels(&connection_id).unwrap(); + + assert_eq!(result.len(), 1); + + assert_eq!(result[0].0, port_id); + assert_eq!(result[0].1, channel_id); + }) +} + +#[test] +fn test_next_sequence_send_ok() { + let sequence_id = Sequence::from(0); + let port_channel = (PortId::default(), ChannelId::default()); + let mut context: Context = Context::new(); + + new_test_ext().execute_with(|| { + assert!(context.store_next_sequence_send(port_channel.clone(), sequence_id).is_ok()); + let result = context.get_next_sequence_send(&port_channel).unwrap(); + assert_eq!(result, sequence_id); + }) +} + +#[test] +fn test_read_conection_channels_failed_by_suppley_error_conneciton_id() { + let connection_id = ConnectionId::new(0); + let connection_id_failed = ConnectionId::new(1); + let port_id = PortId::from_str(String::from_str("port-0").unwrap().as_str()).unwrap(); + let channel_id = ChannelId::from_str(String::from_str("channel-0").unwrap().as_str()).unwrap(); + + let mut context: Context = Context::new(); + new_test_ext().execute_with(|| { + assert!(context + .store_connection_channels( + connection_id.clone(), + &(port_id.clone(), channel_id.clone()) + ) + .is_ok()); + + let result = context.connection_channels(&connection_id_failed).unwrap_err().to_string(); + + assert_eq!( + result, + ICS04Error::connection_not_open(connection_id_failed.clone()).to_string() + ); + }) +} + +#[test] +fn test_store_channel_ok() { + let port_id = PortId::default(); + let channel_id = ChannelId::default(); + let channel_end = ChannelEnd::default(); + + let mut context: Context = Context::new(); + + new_test_ext().execute_with(|| { + assert!(context + .store_channel((port_id.clone(), channel_id.clone()), &channel_end) + .is_ok()); + + let result = context.channel_end(&(port_id.clone(), channel_id.clone())).unwrap(); + + assert_eq!(result, channel_end); + }) +} + +#[test] + +fn test_next_sequence_send_fail() { + let port_channel = (PortId::default(), ChannelId::default()); + let context: Context = Context::new(); + + new_test_ext().execute_with(|| { + let result = context.get_next_sequence_send(&port_channel.clone()).unwrap_err().to_string(); + assert_eq!(result, ICS04Error::missing_next_send_seq(port_channel).to_string()); + }) +} + +#[test] +fn test_next_sequence_recv_ok() { + let sequence_id = Sequence::from(0); + let port_channel = (PortId::default(), ChannelId::default()); + let mut context: Context = Context::new(); + + new_test_ext().execute_with(|| { + assert!(context.store_next_sequence_recv(port_channel.clone(), sequence_id).is_ok()); + let result = context.get_next_sequence_recv(&port_channel).unwrap(); + assert_eq!(result, sequence_id); + }) +} + +#[test] +fn test_get_identified_channel_end() { + let range = (0..10).into_iter().collect::>(); + + let mut port_id_vec = vec![]; + let mut channel_id_vec = vec![]; + let channel_end_vec = vec![ChannelEnd::default(); range.len()]; + + for index in 0..range.len() { + port_id_vec.push(PortId::default()); + channel_id_vec.push(ChannelId::default()); + } + + let mut context: Context = Context::new(); + new_test_ext().execute_with(|| { + for index in 0..range.len() { + assert!(context + .store_channel( + (port_id_vec[index].clone(), channel_id_vec[index].clone()), + &channel_end_vec[index].clone() + ) + .is_ok()); + } + }) +} + +#[test] +fn test_next_sequence_recv_fail() { + let port_channel = (PortId::default(), ChannelId::default()); + let context: Context = Context::new(); + + new_test_ext().execute_with(|| { + let result = context.get_next_sequence_recv(&port_channel.clone()).unwrap_err().to_string(); + assert_eq!(result, ICS04Error::missing_next_recv_seq(port_channel).to_string()); + }) +} + +#[test] +fn test_next_sequence_ack_ok() { + let sequence_id = Sequence::from(0); + let port_channel = (PortId::default(), ChannelId::default()); + let mut context: Context = Context::new(); + + new_test_ext().execute_with(|| { + assert!(context.store_next_sequence_ack(port_channel.clone(), sequence_id).is_ok()); + let result = context.get_next_sequence_ack(&port_channel).unwrap(); + assert_eq!(result, sequence_id); + }) +} + +#[test] +fn test_next_sequence_ack_fail() { + let port_channel = (PortId::default(), ChannelId::default()); + let context: Context = Context::new(); + + new_test_ext().execute_with(|| { + let result = context.get_next_sequence_ack(&port_channel.clone()).unwrap_err().to_string(); + assert_eq!(result, ICS04Error::missing_next_ack_seq(port_channel).to_string()); + }) +} diff --git a/frame/ibc/src/traits.rs b/frame/ibc/src/traits.rs new file mode 100644 index 0000000000000..6ff204fc02a0c --- /dev/null +++ b/frame/ibc/src/traits.rs @@ -0,0 +1,27 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use alloc::vec::Vec; + +/// A trait handling asset ID and name +pub trait AssetIdAndNameProvider { + type Err; + + fn try_get_asset_id(name: impl AsRef<[u8]>) -> Result; + + fn try_get_asset_name(asset_id: AssetId) -> Result, Self::Err>; +} diff --git a/frame/ibc/src/utils.rs b/frame/ibc/src/utils.rs new file mode 100644 index 0000000000000..cd1917b5e7e98 --- /dev/null +++ b/frame/ibc/src/utils.rs @@ -0,0 +1,64 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use crate::Config; +use codec::Encode; +use scale_info::prelude::{fmt::Debug, format, vec::Vec}; + +use super::*; +use ibc::{ + applications::transfer::{error::Error as Ics20Error, VERSION}, + core::ics24_host::identifier::{ChannelId as IbcChannelId, PortId}, + signer::Signer, +}; + +use ibc::{ + core::{ + ics02_client::msgs::ClientMsg, + ics03_connection::msgs::ConnectionMsg, + ics04_channel::msgs::{ChannelMsg, PacketMsg}, + ics26_routing::{handler, msgs::Ics26Envelope}, + }, + events::IbcEvent, +}; + +/// Get the latest block height of the host chain +pub fn host_height() -> u64 { + let block_number = format!("{:?}", >::block_number()); + let current_height: u64 = block_number.parse().unwrap_or_default(); + current_height +} + +/// In ICS20 fungible token transfer, get the escrow address by channel ID and port ID +/// +/// Parameters: +/// - `port_id`: The ID of the port corresponding to the escrow. +/// - `channel_id`: The ID of the channel corresponding to the escrow. +pub fn get_channel_escrow_address( + port_id: &PortId, + channel_id: &IbcChannelId, +) -> Result { + let contents = format!("{}/{}", port_id, channel_id); + let mut data = VERSION.as_bytes().to_vec(); + data.extend_from_slice(&[0]); + data.extend_from_slice(contents.as_bytes()); + + let hash = sp_io::hashing::sha2_256(&data).to_vec(); + let mut hex_string = hex::encode_upper(hash); + hex_string.insert_str(0, "0x"); + hex_string.parse::().map_err(Ics20Error::signer) +}