mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 18:51:12 +00:00
Move sc-client into sc-service (#5502)
* Drop client from sc-network and sc-client-db, move LongestChain to sc-client-api * move leaves, cht, in_mem to sc-client-api, drop client from sc-finality-grandpa * drop sc-service from sc-rpc * drop sc-service from sc-consensus-aura * drop sc-client from manual-seal and babe * drop sc-client from utils/frame/rpc/system and utils/frame/benchmarking-cli * drop sc-client from bin/node and bin/node-template * drop sc-client * fix tests * remove check -p sc-client from gitlab.yml * fix warnings * fixes ui test * fix light client tests * adds associated Client type to AbstractService * adds UsageProvider to Client * fixed ui test, again * tried and failed to get node-cli to compile for wasm * thanks to tomaka for helping me get node-cli to compile for wasmm * ui test pls pas 🙏🏾 * all tests passing 🪄 * no_run documentation code * rm -f documentation code * ClientProvider * fix mega trait * move LongestChain to sc-consensus, use adds minimal bounds to AbstractService::Client * adds license to sc-consensus Co-authored-by: Benjamin Kampmann <ben@parity.io>
This commit is contained in:
@@ -326,7 +326,6 @@ check-web-wasm:
|
||||
- time cargo build --target=wasm32-unknown-unknown -p sp-io
|
||||
- time cargo build --target=wasm32-unknown-unknown -p sp-runtime
|
||||
- time cargo build --target=wasm32-unknown-unknown -p sp-std
|
||||
- time cargo build --target=wasm32-unknown-unknown -p sc-client
|
||||
- time cargo build --target=wasm32-unknown-unknown -p sc-consensus-aura
|
||||
- time cargo build --target=wasm32-unknown-unknown -p sc-consensus-babe
|
||||
- time cargo build --target=wasm32-unknown-unknown -p sp-consensus
|
||||
|
||||
Generated
+96
-108
@@ -126,15 +126,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75153c95fdedd7db9732dfbfc3702324a1627eec91ba56e37cd0ac78314ab2ed"
|
||||
checksum = "1148c9b25d393a07c4cc3ef5dd30f82a40a1c261018c4a670611ed8e76cad3ea"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "0.4.5"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825"
|
||||
checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
@@ -280,9 +280,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.35"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118"
|
||||
checksum = "78848718ee1255a2485d1309ad9cdecfc2e7d0362dd11c6829364c6b35ae1bc7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -446,9 +446,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bs58"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae"
|
||||
checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
@@ -547,9 +547,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||
checksum = "9c9384ca4b90c0ea47e19a5c996d6643a3e73dedf9b89c65efb67587e34da1bb"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
@@ -1140,18 +1140,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2"
|
||||
version = "0.6.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a80e524ebf194285b57e5e7944018721c7fffc673253f5183f7accd88a2a3b0c"
|
||||
checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0"
|
||||
dependencies = [
|
||||
"enumflags2_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2_derive"
|
||||
version = "0.6.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ed9afacaea0301eefb738c9deea725e6d53938004597cdc518a8cf9a7aa2f03"
|
||||
checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.3",
|
||||
@@ -1426,7 +1426,6 @@ dependencies = [
|
||||
"frame-benchmarking",
|
||||
"parity-scale-codec",
|
||||
"sc-cli",
|
||||
"sc-client",
|
||||
"sc-client-db",
|
||||
"sc-executor",
|
||||
"sc-service",
|
||||
@@ -1980,9 +1979,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
|
||||
checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -2135,9 +2134,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.13.4"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed6081100e960d9d74734659ffc9cc91daf1c0fc7aceb8eaa94ee1a3f5046f2e"
|
||||
checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14"
|
||||
dependencies = [
|
||||
"bytes 0.5.4",
|
||||
"futures-channel",
|
||||
@@ -2166,7 +2165,7 @@ dependencies = [
|
||||
"bytes 0.5.4",
|
||||
"ct-logs",
|
||||
"futures-util",
|
||||
"hyper 0.13.4",
|
||||
"hyper 0.13.5",
|
||||
"log",
|
||||
"rustls",
|
||||
"rustls-native-certs",
|
||||
@@ -3431,9 +3430,9 @@ dependencies = [
|
||||
"sc-basic-authorship",
|
||||
"sc-chain-spec",
|
||||
"sc-cli",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-client-db",
|
||||
"sc-consensus",
|
||||
"sc-consensus-babe",
|
||||
"sc-consensus-epochs",
|
||||
"sc-finality-grandpa",
|
||||
@@ -3538,7 +3537,7 @@ dependencies = [
|
||||
"node-runtime",
|
||||
"pallet-contracts-rpc",
|
||||
"pallet-transaction-payment-rpc",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-consensus-babe",
|
||||
"sc-consensus-babe-rpc",
|
||||
"sc-consensus-epochs",
|
||||
@@ -3638,8 +3637,8 @@ dependencies = [
|
||||
"node-template-runtime",
|
||||
"sc-basic-authorship",
|
||||
"sc-cli",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-consensus",
|
||||
"sc-consensus-aura",
|
||||
"sc-executor",
|
||||
"sc-finality-grandpa",
|
||||
@@ -3715,7 +3714,6 @@ dependencies = [
|
||||
"parity-scale-codec",
|
||||
"sc-block-builder",
|
||||
"sc-cli",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-client-db",
|
||||
"sc-executor",
|
||||
@@ -3744,7 +3742,6 @@ dependencies = [
|
||||
"parity-scale-codec",
|
||||
"sc-block-builder",
|
||||
"sc-cli",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-service",
|
||||
"sp-api",
|
||||
@@ -3850,9 +3847,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.12.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
@@ -4875,7 +4872,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core 0.7.1",
|
||||
"parking_lot_core 0.7.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4895,9 +4892,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb"
|
||||
checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cloudabi",
|
||||
@@ -5568,18 +5565,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "077f197a31bfe7e4169145f9eca08d32705c6c6126c139c26793acdf163ac3ef"
|
||||
checksum = "0a214c7875e1b63fc1618db7c80efc0954f6156c9ff07699fd9039e255accdd1"
|
||||
dependencies = [
|
||||
"ref-cast-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast-impl"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c36eb52b69b87c9e3a07387f476c88fd0dba9a1713b38e56617ed66b45392c1f"
|
||||
checksum = "602eb59cda66fcb9aec25841fb76bc01d2b34282dcdd705028da297db6f3eec8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.3",
|
||||
@@ -5588,9 +5585,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.6"
|
||||
version = "1.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3"
|
||||
checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -5952,47 +5949,6 @@ dependencies = [
|
||||
"tokio 0.2.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sc-client"
|
||||
version = "0.8.0-dev"
|
||||
dependencies = [
|
||||
"derive_more",
|
||||
"env_logger 0.7.1",
|
||||
"fnv",
|
||||
"futures 0.3.4",
|
||||
"hash-db",
|
||||
"hex-literal",
|
||||
"kvdb",
|
||||
"kvdb-memorydb",
|
||||
"log",
|
||||
"parity-scale-codec",
|
||||
"parking_lot 0.10.2",
|
||||
"rand 0.7.3",
|
||||
"sc-block-builder",
|
||||
"sc-client-api",
|
||||
"sc-executor",
|
||||
"sc-telemetry",
|
||||
"sp-api",
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-core",
|
||||
"sp-database",
|
||||
"sp-externalities",
|
||||
"sp-inherents",
|
||||
"sp-keyring",
|
||||
"sp-panic-handler",
|
||||
"sp-runtime",
|
||||
"sp-state-machine",
|
||||
"sp-std",
|
||||
"sp-trie",
|
||||
"sp-utils",
|
||||
"sp-version",
|
||||
"substrate-prometheus-endpoint",
|
||||
"substrate-test-runtime-client",
|
||||
"tempfile",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sc-client-api"
|
||||
version = "2.0.0-dev"
|
||||
@@ -6003,6 +5959,7 @@ dependencies = [
|
||||
"hash-db",
|
||||
"hex-literal",
|
||||
"kvdb",
|
||||
"kvdb-memorydb",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"parity-scale-codec",
|
||||
@@ -6013,6 +5970,7 @@ dependencies = [
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-core",
|
||||
"sp-database",
|
||||
"sp-externalities",
|
||||
"sp-inherents",
|
||||
"sp-keyring",
|
||||
@@ -6026,6 +5984,7 @@ dependencies = [
|
||||
"sp-utils",
|
||||
"sp-version",
|
||||
"substrate-prometheus-endpoint",
|
||||
"substrate-test-runtime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6045,7 +6004,6 @@ dependencies = [
|
||||
"parity-util-mem",
|
||||
"parking_lot 0.10.2",
|
||||
"quickcheck",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-executor",
|
||||
"sc-state-db",
|
||||
@@ -6062,6 +6020,16 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sc-consensus"
|
||||
version = "0.8.0-dev"
|
||||
dependencies = [
|
||||
"sc-client-api",
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-runtime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sc-consensus-aura"
|
||||
version = "0.8.0-dev"
|
||||
@@ -6074,7 +6042,6 @@ dependencies = [
|
||||
"parity-scale-codec",
|
||||
"parking_lot 0.10.2",
|
||||
"sc-block-builder",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-consensus-slots",
|
||||
"sc-executor",
|
||||
@@ -6119,7 +6086,6 @@ dependencies = [
|
||||
"pdqselect",
|
||||
"rand 0.7.3",
|
||||
"sc-block-builder",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-consensus-epochs",
|
||||
"sc-consensus-slots",
|
||||
@@ -6201,7 +6167,6 @@ dependencies = [
|
||||
"log",
|
||||
"parking_lot 0.10.2",
|
||||
"sc-basic-authorship",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-transaction-pool",
|
||||
"serde",
|
||||
@@ -6372,8 +6337,8 @@ dependencies = [
|
||||
"pin-project",
|
||||
"rand 0.7.3",
|
||||
"sc-block-builder",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-consensus",
|
||||
"sc-keystore",
|
||||
"sc-network",
|
||||
"sc-network-gossip",
|
||||
@@ -6463,7 +6428,6 @@ dependencies = [
|
||||
"quickcheck",
|
||||
"rand 0.7.3",
|
||||
"sc-block-builder",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-peerset",
|
||||
"serde",
|
||||
@@ -6520,9 +6484,10 @@ dependencies = [
|
||||
"parking_lot 0.10.2",
|
||||
"rand 0.7.3",
|
||||
"sc-block-builder",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-consensus",
|
||||
"sc-network",
|
||||
"sc-service",
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-consensus-babe",
|
||||
@@ -6543,7 +6508,7 @@ dependencies = [
|
||||
"fnv",
|
||||
"futures 0.3.4",
|
||||
"futures-timer 3.0.2",
|
||||
"hyper 0.13.4",
|
||||
"hyper 0.13.5",
|
||||
"hyper-rustls",
|
||||
"log",
|
||||
"num_cpus",
|
||||
@@ -6593,7 +6558,6 @@ dependencies = [
|
||||
"parity-scale-codec",
|
||||
"parking_lot 0.10.2",
|
||||
"sc-block-builder",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-executor",
|
||||
"sc-keystore",
|
||||
@@ -6677,6 +6641,7 @@ dependencies = [
|
||||
"futures 0.1.29",
|
||||
"futures 0.3.4",
|
||||
"futures-timer 3.0.2",
|
||||
"hash-db",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"netstat2",
|
||||
@@ -6686,8 +6651,9 @@ dependencies = [
|
||||
"parking_lot 0.10.2",
|
||||
"pin-project",
|
||||
"procfs",
|
||||
"rand 0.7.3",
|
||||
"sc-block-builder",
|
||||
"sc-chain-spec",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-client-db",
|
||||
"sc-executor",
|
||||
@@ -6705,16 +6671,21 @@ dependencies = [
|
||||
"slog",
|
||||
"sp-api",
|
||||
"sp-application-crypto",
|
||||
"sp-block-builder",
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-consensus-babe",
|
||||
"sp-core",
|
||||
"sp-externalities",
|
||||
"sp-finality-grandpa",
|
||||
"sp-io",
|
||||
"sp-runtime",
|
||||
"sp-session",
|
||||
"sp-state-machine",
|
||||
"sp-transaction-pool",
|
||||
"sp-trie",
|
||||
"sp-utils",
|
||||
"sp-version",
|
||||
"substrate-prometheus-endpoint",
|
||||
"substrate-test-runtime-client",
|
||||
"sysinfo",
|
||||
@@ -6730,14 +6701,29 @@ dependencies = [
|
||||
"fdlimit",
|
||||
"futures 0.1.29",
|
||||
"futures 0.3.4",
|
||||
"hex-literal",
|
||||
"log",
|
||||
"sc-client",
|
||||
"parity-scale-codec",
|
||||
"parking_lot 0.10.2",
|
||||
"sc-block-builder",
|
||||
"sc-client-api",
|
||||
"sc-client-db",
|
||||
"sc-executor",
|
||||
"sc-network",
|
||||
"sc-service",
|
||||
"sp-api",
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-core",
|
||||
"sp-externalities",
|
||||
"sp-panic-handler",
|
||||
"sp-runtime",
|
||||
"sp-state-machine",
|
||||
"sp-storage",
|
||||
"sp-transaction-pool",
|
||||
"sp-trie",
|
||||
"substrate-test-runtime",
|
||||
"substrate-test-runtime-client",
|
||||
"tempfile",
|
||||
"tokio 0.1.22",
|
||||
]
|
||||
@@ -7935,9 +7921,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff6da2e8d107dfd7b74df5ef4d205c6aebee0706c647f6bc6a2d5789905c00fb"
|
||||
checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static",
|
||||
@@ -7946,9 +7932,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.6"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a489c87c08fbaf12e386665109dd13470dcc9c4583ea3e10dd2b4523e5ebd9ac"
|
||||
checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@@ -8080,7 +8066,7 @@ dependencies = [
|
||||
"jsonrpc-derive",
|
||||
"log",
|
||||
"parity-scale-codec",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-transaction-pool",
|
||||
"serde",
|
||||
"sp-api",
|
||||
@@ -8098,7 +8084,7 @@ dependencies = [
|
||||
"async-std",
|
||||
"derive_more",
|
||||
"futures-util",
|
||||
"hyper 0.13.4",
|
||||
"hyper 0.13.5",
|
||||
"log",
|
||||
"prometheus",
|
||||
"tokio 0.2.18",
|
||||
@@ -8111,10 +8097,11 @@ dependencies = [
|
||||
"futures 0.3.4",
|
||||
"hash-db",
|
||||
"parity-scale-codec",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-client-db",
|
||||
"sc-consensus",
|
||||
"sc-executor",
|
||||
"sc-service",
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-core",
|
||||
@@ -8139,8 +8126,8 @@ dependencies = [
|
||||
"parity-scale-codec",
|
||||
"parity-util-mem",
|
||||
"sc-block-builder",
|
||||
"sc-client",
|
||||
"sc-executor",
|
||||
"sc-service",
|
||||
"serde",
|
||||
"sp-api",
|
||||
"sp-application-crypto",
|
||||
@@ -8172,10 +8159,12 @@ dependencies = [
|
||||
"futures 0.3.4",
|
||||
"parity-scale-codec",
|
||||
"sc-block-builder",
|
||||
"sc-client",
|
||||
"sc-client-api",
|
||||
"sc-consensus",
|
||||
"sc-service",
|
||||
"sp-api",
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-core",
|
||||
"sp-runtime",
|
||||
"substrate-test-client",
|
||||
@@ -8357,9 +8346,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.13.3"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a0338198966bde7feb14b011a33d404a62a6e03b843352c71512a2a002634b7"
|
||||
checksum = "1cac193374347e7c263c5f547524f36ff8ec6702d56c8799c8331d26dffe8c1e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"doc-comment",
|
||||
@@ -8467,12 +8456,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.42"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
@@ -9355,18 +9343,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wast"
|
||||
version = "13.0.0"
|
||||
version = "14.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b20abd8b4a26f7e0d4dd5e357e90a3d555ec190e94472c9b2b27c5b9777f9ae"
|
||||
checksum = "47b11c94c63d5365a76ea287f8e6e5b6050233fae4b2423aea2a1e126a385e17"
|
||||
dependencies = [
|
||||
"leb128",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wat"
|
||||
version = "1.0.14"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51a615830ee3e7200b505c441fec09aac2f114deae69df52f215cb828ba112c4"
|
||||
checksum = "03db18bc33cff3859c296efbefdcc00763a644539feeadca3415a1cee8a2835d"
|
||||
dependencies = [
|
||||
"wast",
|
||||
]
|
||||
@@ -9448,9 +9436,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
@@ -15,7 +15,6 @@ members = [
|
||||
"bin/node/transaction-factory",
|
||||
"bin/utils/subkey",
|
||||
"bin/utils/chain-spec-builder",
|
||||
"client",
|
||||
"client/api",
|
||||
"client/authority-discovery",
|
||||
"client/basic-authorship",
|
||||
@@ -26,6 +25,7 @@ members = [
|
||||
"client/consensus/aura",
|
||||
"client/consensus/babe",
|
||||
"client/consensus/babe/rpc",
|
||||
"client/consensus/common",
|
||||
"client/consensus/manual-seal",
|
||||
"client/consensus/pow",
|
||||
"client/consensus/uncles",
|
||||
|
||||
@@ -23,7 +23,7 @@ structopt = "0.3.8"
|
||||
sc-cli = { version = "0.8.0-dev", path = "../../../client/cli" }
|
||||
sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "../../../client/executor" }
|
||||
sc-service = { version = "0.8.0-dev", path = "../../../client/service" }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, path = "../../../client/service" }
|
||||
sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" }
|
||||
sc-transaction-pool = { version = "2.0.0-dev", path = "../../../client/transaction-pool" }
|
||||
sp-transaction-pool = { version = "2.0.0-dev", path = "../../../primitives/transaction-pool" }
|
||||
@@ -31,9 +31,9 @@ sc-network = { version = "0.8.0-dev", path = "../../../client/network" }
|
||||
sc-consensus-aura = { version = "0.8.0-dev", path = "../../../client/consensus/aura" }
|
||||
sp-consensus-aura = { version = "0.8.0-dev", path = "../../../primitives/consensus/aura" }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" }
|
||||
sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" }
|
||||
sc-finality-grandpa = { version = "0.8.0-dev", path = "../../../client/finality-grandpa" }
|
||||
sp-finality-grandpa = { version = "2.0.0-dev", path = "../../../primitives/finality-grandpa" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../../client/" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" }
|
||||
sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" }
|
||||
sc-basic-authorship = { path = "../../../client/basic-authorship", version = "0.8.0-dev"}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use sc_client::LongestChain;
|
||||
use sc_client_api::ExecutorProvider;
|
||||
use sc_consensus::LongestChain;
|
||||
use node_template_runtime::{self, opaque::Block, RuntimeApi};
|
||||
use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder};
|
||||
use sp_inherents::InherentDataProviders;
|
||||
@@ -35,7 +35,7 @@ macro_rules! new_full_start {
|
||||
node_template_runtime::opaque::Block, node_template_runtime::RuntimeApi, crate::service::Executor
|
||||
>($config)?
|
||||
.with_select_chain(|_config, backend| {
|
||||
Ok(sc_client::LongestChain::new(backend.clone()))
|
||||
Ok(sc_consensus::LongestChain::new(backend.clone()))
|
||||
})?
|
||||
.with_transaction_pool(|config, client, _fetcher, prometheus_registry| {
|
||||
let pool_api = sc_transaction_pool::FullChainApi::new(client.clone());
|
||||
@@ -71,9 +71,7 @@ macro_rules! new_full_start {
|
||||
}
|
||||
|
||||
/// Builds a new service for a full client.
|
||||
pub fn new_full(config: Configuration)
|
||||
-> Result<impl AbstractService, ServiceError>
|
||||
{
|
||||
pub fn new_full(config: Configuration) -> Result<impl AbstractService, ServiceError> {
|
||||
let role = config.role.clone();
|
||||
let force_authoring = config.force_authoring;
|
||||
let name = config.network.node_name.clone();
|
||||
@@ -176,9 +174,7 @@ pub fn new_full(config: Configuration)
|
||||
}
|
||||
|
||||
/// Builds a new service for a light client.
|
||||
pub fn new_light(config: Configuration)
|
||||
-> Result<impl AbstractService, ServiceError>
|
||||
{
|
||||
pub fn new_light(config: Configuration) -> Result<impl AbstractService, ServiceError> {
|
||||
let inherent_data_providers = InherentDataProviders::new();
|
||||
|
||||
ServiceBuilder::new_light::<Block, RuntimeApi, Executor>(config)?
|
||||
|
||||
@@ -60,8 +60,8 @@ sp-transaction-pool = { version = "2.0.0-dev", path = "../../../primitives/trans
|
||||
|
||||
# client dependencies
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../../client/" }
|
||||
sc-chain-spec = { version = "2.0.0-dev", path = "../../../client/chain-spec" }
|
||||
sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" }
|
||||
sc-transaction-pool = { version = "2.0.0-dev", path = "../../../client/transaction-pool" }
|
||||
sc-network = { version = "0.8.0-dev", path = "../../../client/network" }
|
||||
sc-consensus-babe = { version = "0.8.0-dev", path = "../../../client/consensus/babe" }
|
||||
@@ -111,6 +111,7 @@ sc-service = { version = "0.8.0-dev", default-features = false, path = "../../..
|
||||
|
||||
[dev-dependencies]
|
||||
sc-keystore = { version = "2.0.0-dev", path = "../../../client/keystore" }
|
||||
sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" }
|
||||
sc-consensus-babe = { version = "0.8.0-dev", features = ["test-helpers"], path = "../../../client/consensus/babe" }
|
||||
sc-consensus-epochs = { version = "0.8.0-dev", path = "../../../client/consensus/epochs" }
|
||||
sc-service-test = { version = "2.0.0-dev", path = "../../../client/service/test" }
|
||||
|
||||
@@ -51,9 +51,9 @@ const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Extensions {
|
||||
/// Block numbers with known hashes.
|
||||
pub fork_blocks: sc_client::ForkBlocks<Block>,
|
||||
pub fork_blocks: sc_client_api::ForkBlocks<Block>,
|
||||
/// Known bad block hashes.
|
||||
pub bad_blocks: sc_client::BadBlocks<Block>,
|
||||
pub bad_blocks: sc_client_api::BadBlocks<Block>,
|
||||
}
|
||||
|
||||
/// Specialized `ChainSpec`.
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use sc_consensus_babe;
|
||||
use sc_client::{self, LongestChain};
|
||||
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider};
|
||||
use node_executor;
|
||||
use node_primitives::Block;
|
||||
@@ -30,14 +29,7 @@ use sc_service::{
|
||||
AbstractService, ServiceBuilder, config::Configuration, error::{Error as ServiceError},
|
||||
};
|
||||
use sp_inherents::InherentDataProviders;
|
||||
|
||||
use sc_service::{Service, NetworkStatus};
|
||||
use sc_client::{Client, LocalCallExecutor};
|
||||
use sc_client_db::Backend;
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
use node_executor::NativeExecutor;
|
||||
use sc_network::NetworkService;
|
||||
use sc_offchain::OffchainWorkers;
|
||||
use sc_consensus::LongestChain;
|
||||
|
||||
/// Starts a `ServiceBuilder` for a full service.
|
||||
///
|
||||
@@ -54,7 +46,7 @@ macro_rules! new_full_start {
|
||||
node_primitives::Block, node_runtime::RuntimeApi, node_executor::Executor
|
||||
>($config)?
|
||||
.with_select_chain(|_config, backend| {
|
||||
Ok(sc_client::LongestChain::new(backend.clone()))
|
||||
Ok(sc_consensus::LongestChain::new(backend.clone()))
|
||||
})?
|
||||
.with_transaction_pool(|config, client, _fetcher, prometheus_registry| {
|
||||
let pool_api = sc_transaction_pool::FullChainApi::new(client.clone());
|
||||
@@ -266,38 +258,9 @@ macro_rules! new_full {
|
||||
}}
|
||||
}
|
||||
|
||||
type ConcreteBlock = node_primitives::Block;
|
||||
type ConcreteClient =
|
||||
Client<
|
||||
Backend<ConcreteBlock>,
|
||||
LocalCallExecutor<Backend<ConcreteBlock>, NativeExecutor<node_executor::Executor>>,
|
||||
ConcreteBlock,
|
||||
node_runtime::RuntimeApi
|
||||
>;
|
||||
type ConcreteBackend = Backend<ConcreteBlock>;
|
||||
type ConcreteTransactionPool = sc_transaction_pool::BasicPool<
|
||||
sc_transaction_pool::FullChainApi<ConcreteClient, ConcreteBlock>,
|
||||
ConcreteBlock
|
||||
>;
|
||||
|
||||
/// Builds a new service for a full client.
|
||||
pub fn new_full(config: Configuration)
|
||||
-> Result<
|
||||
Service<
|
||||
ConcreteBlock,
|
||||
ConcreteClient,
|
||||
LongestChain<ConcreteBackend, ConcreteBlock>,
|
||||
NetworkStatus<ConcreteBlock>,
|
||||
NetworkService<ConcreteBlock, <ConcreteBlock as BlockT>::Hash>,
|
||||
ConcreteTransactionPool,
|
||||
OffchainWorkers<
|
||||
ConcreteClient,
|
||||
<ConcreteBackend as sc_client_api::backend::Backend<Block>>::OffchainStorage,
|
||||
ConcreteBlock,
|
||||
>
|
||||
>,
|
||||
ServiceError,
|
||||
>
|
||||
-> Result<impl AbstractService, ServiceError>
|
||||
{
|
||||
new_full!(config).map(|(service, _)| service)
|
||||
}
|
||||
@@ -416,7 +379,7 @@ mod tests {
|
||||
use sp_core::ed25519::Pair;
|
||||
|
||||
use {service_test, Factory};
|
||||
use sc_client::{BlockImportParams, BlockOrigin};
|
||||
use sp_consensus::{BlockImportParams, BlockOrigin};
|
||||
|
||||
let alice: Arc<ed25519::Pair> = Arc::new(Keyring::Alice.into());
|
||||
let bob: Arc<ed25519::Pair> = Arc::new(Keyring::Bob.into());
|
||||
|
||||
@@ -11,7 +11,7 @@ repository = "https://github.com/paritytech/substrate/"
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
sc-client = { version = "0.8.0-dev", path = "../../../client/" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" }
|
||||
jsonrpc-core = "14.0.3"
|
||||
node-primitives = { version = "2.0.0-dev", path = "../primitives" }
|
||||
node-runtime = { version = "2.0.0-dev", path = "../runtime" }
|
||||
|
||||
@@ -50,7 +50,7 @@ pub struct LightDeps<C, F, P> {
|
||||
/// Transaction pool instance.
|
||||
pub pool: Arc<P>,
|
||||
/// Remote access to the blockchain (async).
|
||||
pub remote_blockchain: Arc<dyn sc_client::light::blockchain::RemoteBlockchain<Block>>,
|
||||
pub remote_blockchain: Arc<dyn sc_client_api::light::RemoteBlockchain<Block>>,
|
||||
/// Fetcher instance.
|
||||
pub fetcher: Arc<F>,
|
||||
}
|
||||
@@ -135,9 +135,9 @@ pub fn create_full<C, P, M, SC>(
|
||||
pub fn create_light<C, P, M, F>(
|
||||
deps: LightDeps<C, F, P>,
|
||||
) -> jsonrpc_core::IoHandler<M> where
|
||||
C: sc_client::blockchain::HeaderBackend<Block>,
|
||||
C: sp_blockchain::HeaderBackend<Block>,
|
||||
C: Send + Sync + 'static,
|
||||
F: sc_client::light::fetcher::Fetcher<Block> + 'static,
|
||||
F: sc_client_api::light::Fetcher<Block> + 'static,
|
||||
P: TransactionPool + 'static,
|
||||
M: jsonrpc_core::Metadata + Default,
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
pallet-balances = { version = "2.0.0-dev", path = "../../../frame/balances" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../../client/" }
|
||||
sc-service = { version = "0.8.0-dev", features = ["test-helpers", "db"], path = "../../../client/service" }
|
||||
sc-client-db = { version = "0.8.0-dev", path = "../../../client/db/", features = ["kvdb-rocksdb", "parity-db"] }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../../client/api/" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0" }
|
||||
@@ -55,4 +55,3 @@ futures = "0.3.1"
|
||||
[dev-dependencies]
|
||||
criterion = "0.3.0"
|
||||
sc-cli = { version = "0.8.0-dev", path = "../../../client/cli" }
|
||||
sc-service = { version = "0.8.0-dev", path = "../../../client/service", features = ["db"] }
|
||||
|
||||
@@ -221,7 +221,7 @@ impl BenchDb {
|
||||
},
|
||||
};
|
||||
|
||||
let (client, backend) = sc_client_db::new_client(
|
||||
let (client, backend) = sc_service::new_client(
|
||||
db_config,
|
||||
NativeExecutor::new(WasmExecutionMethod::Compiled, None, 8),
|
||||
&keyring.generate_genesis(),
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Utilities to build a `TestClient` for `node-runtime`.
|
||||
|
||||
use sp_runtime::BuildStorage;
|
||||
|
||||
use sc_service::client;
|
||||
/// Re-export test-client utilities.
|
||||
pub use substrate_test_client::*;
|
||||
|
||||
@@ -28,9 +28,9 @@ pub type Executor = sc_executor::NativeExecutor<node_executor::Executor>;
|
||||
pub type Backend = sc_client_db::Backend<node_primitives::Block>;
|
||||
|
||||
/// Test client type.
|
||||
pub type Client = sc_client::Client<
|
||||
pub type Client = client::Client<
|
||||
Backend,
|
||||
sc_client::LocalCallExecutor<Backend, Executor>,
|
||||
client::LocalCallExecutor<Backend, Executor>,
|
||||
node_primitives::Block,
|
||||
node_runtime::RuntimeApi,
|
||||
>;
|
||||
@@ -61,7 +61,7 @@ pub trait TestClientBuilderExt: Sized {
|
||||
|
||||
impl TestClientBuilderExt for substrate_test_client::TestClientBuilder<
|
||||
node_primitives::Block,
|
||||
sc_client::LocalCallExecutor<Backend, Executor>,
|
||||
client::LocalCallExecutor<Backend, Executor>,
|
||||
Backend,
|
||||
GenesisParameters,
|
||||
> {
|
||||
|
||||
@@ -15,7 +15,6 @@ sp-block-builder = { version = "2.0.0-dev", path = "../../../primitives/block-bu
|
||||
sc-cli = { version = "0.8.0-dev", path = "../../../client/cli" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" }
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "../../../client/block-builder" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../../client" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" }
|
||||
log = "0.4.8"
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
[package]
|
||||
name = "sc-client"
|
||||
version = "0.8.0-dev"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
license = "GPL-3.0"
|
||||
homepage = "https://substrate.dev"
|
||||
repository = "https://github.com/paritytech/substrate/"
|
||||
description = "Substrate Client and associated logic."
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "block-builder" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "api" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../primitives/consensus/common" }
|
||||
derive_more = { version = "0.99.2" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "executor" }
|
||||
sp-externalities = { version = "0.8.0-dev", path = "../primitives/externalities" }
|
||||
fnv = { version = "1.0.6" }
|
||||
futures = { version = "0.3.1", features = ["compat"] }
|
||||
hash-db = { version = "0.15.2" }
|
||||
hex-literal = { version = "0.2.1" }
|
||||
sp-inherents = { version = "2.0.0-dev", path = "../primitives/inherents" }
|
||||
sp-keyring = { version = "2.0.0-dev", path = "../primitives/keyring" }
|
||||
kvdb = "0.5.0"
|
||||
log = { version = "0.4.8" }
|
||||
parking_lot = "0.10.0"
|
||||
rand = "0.7.3"
|
||||
sp-core = { version = "2.0.0-dev", path = "../primitives/core" }
|
||||
sp-std = { version = "2.0.0-dev", path = "../primitives/std" }
|
||||
sp-version = { version = "2.0.0-dev", path = "../primitives/version" }
|
||||
sp-api = { version = "2.0.0-dev", path = "../primitives/api" }
|
||||
sp-runtime = { version = "2.0.0-dev", path = "../primitives/runtime" }
|
||||
sp-utils = { version = "2.0.0-dev", path = "../primitives/utils" }
|
||||
sp-blockchain = { version = "2.0.0-dev", path = "../primitives/blockchain" }
|
||||
sp-state-machine = { version = "0.8.0-dev", path = "../primitives/state-machine" }
|
||||
sc-telemetry = { version = "2.0.0-dev", path = "telemetry" }
|
||||
sp-trie = { version = "2.0.0-dev", path = "../primitives/trie" }
|
||||
sp-database = { version = "2.0.0-dev", path = "../primitives/database" }
|
||||
prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-dev", path = "../utils/prometheus" }
|
||||
tracing = "0.1.10"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.7.0"
|
||||
tempfile = "3.1.0"
|
||||
substrate-test-runtime-client = { version = "2.0.0-dev", path = "../test-utils/runtime/client" }
|
||||
kvdb-memorydb = "0.5.0"
|
||||
sp-panic-handler = { version = "2.0.0-dev", path = "../primitives/panic-handler" }
|
||||
@@ -9,10 +9,6 @@ repository = "https://github.com/paritytech/substrate/"
|
||||
description = "Substrate client interfaces."
|
||||
documentation = "https://docs.rs/sc-client-api"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" }
|
||||
@@ -30,6 +26,7 @@ kvdb = "0.5.0"
|
||||
log = { version = "0.4.8" }
|
||||
parking_lot = "0.10.0"
|
||||
lazy_static = "1.4.0"
|
||||
sp-database = { version = "2.0.0-dev", path = "../../primitives/database" }
|
||||
sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" }
|
||||
sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" }
|
||||
sp-version = { version = "2.0.0-dev", default-features = false, path = "../../primitives/version" }
|
||||
@@ -44,4 +41,9 @@ sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transact
|
||||
prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-dev", path = "../../utils/prometheus" }
|
||||
|
||||
[dev-dependencies]
|
||||
kvdb-memorydb = "0.5.0"
|
||||
sp-test-primitives = { version = "2.0.0-dev", path = "../../primitives/test-primitives" }
|
||||
substrate-test-runtime = { version = "2.0.0-dev", path = "../../test-utils/runtime" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
@@ -79,6 +79,25 @@ pub struct ClientImportOperation<Block: BlockT, B: Backend<Block>> {
|
||||
pub notify_finalized: Vec<Block::Hash>,
|
||||
}
|
||||
|
||||
/// Helper function to apply auxiliary data insertion into an operation.
|
||||
pub fn apply_aux<'a, 'b: 'a, 'c: 'a, B, Block, D, I>(
|
||||
operation: &mut ClientImportOperation<Block, B>,
|
||||
insert: I,
|
||||
delete: D,
|
||||
) -> sp_blockchain::Result<()>
|
||||
where
|
||||
Block: BlockT,
|
||||
B: Backend<Block>,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
{
|
||||
operation.op.insert_aux(
|
||||
insert.into_iter()
|
||||
.map(|(k, v)| (k.to_vec(), Some(v.to_vec())))
|
||||
.chain(delete.into_iter().map(|k| (k.to_vec(), None)))
|
||||
)
|
||||
}
|
||||
|
||||
/// State of a new block.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum NewBlockState {
|
||||
|
||||
@@ -331,9 +331,10 @@ pub fn decode_cht_value(value: &[u8]) -> Option<H256> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use substrate_test_runtime_client::runtime::Header;
|
||||
use sp_runtime::traits::BlakeTwo256;
|
||||
use super::*;
|
||||
use sp_runtime::{generic, traits::BlakeTwo256};
|
||||
|
||||
type Header = generic::Header<u64, BlakeTwo256>;
|
||||
|
||||
#[test]
|
||||
fn is_build_required_works() {
|
||||
@@ -32,14 +32,15 @@ use sp_state_machine::{
|
||||
};
|
||||
use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata};
|
||||
|
||||
use sc_client_api::{
|
||||
use crate::{
|
||||
backend::{self, NewBlockState},
|
||||
blockchain::{
|
||||
self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId
|
||||
},
|
||||
UsageInfo,
|
||||
light,
|
||||
leaves::LeafSet,
|
||||
};
|
||||
use crate::leaves::LeafSet;
|
||||
|
||||
struct PendingBlock<B: BlockT> {
|
||||
block: StoredBlock<B>,
|
||||
@@ -400,7 +401,7 @@ impl<Block: BlockT> backend::AuxStore for Blockchain<Block> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> sc_client_api::light::Storage<Block> for Blockchain<Block>
|
||||
impl<Block: BlockT> light::Storage<Block> for Blockchain<Block>
|
||||
where
|
||||
Block::Hash: From<[u8; 32]>,
|
||||
{
|
||||
@@ -454,7 +455,7 @@ impl<Block: BlockT> sc_client_api::light::Storage<Block> for Blockchain<Block>
|
||||
None
|
||||
}
|
||||
|
||||
fn usage_info(&self) -> Option<sc_client_api::UsageInfo> {
|
||||
fn usage_info(&self) -> Option<UsageInfo> {
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -719,7 +720,7 @@ impl<Block: BlockT> backend::RemoteBackend<Block> for Backend<Block> where Block
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn remote_blockchain(&self) -> Arc<dyn crate::light::blockchain::RemoteBlockchain<Block>> {
|
||||
fn remote_blockchain(&self) -> Arc<dyn light::RemoteBlockchain<Block>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -737,46 +738,3 @@ pub fn check_genesis_storage(storage: &Storage) -> sp_blockchain::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use sp_core::offchain::{OffchainStorage, storage::InMemOffchainStorage};
|
||||
use std::sync::Arc;
|
||||
|
||||
type TestBackend = substrate_test_runtime_client::sc_client::in_mem::Backend<substrate_test_runtime_client::runtime::Block>;
|
||||
|
||||
#[test]
|
||||
fn test_leaves_with_complex_block_tree() {
|
||||
let backend = Arc::new(TestBackend::new());
|
||||
|
||||
substrate_test_runtime_client::trait_tests::test_leaves_for_backend(backend);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blockchain_query_by_number_gets_canonical() {
|
||||
let backend = Arc::new(TestBackend::new());
|
||||
|
||||
substrate_test_runtime_client::trait_tests::test_blockchain_query_by_number_gets_canonical(backend);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn in_memory_offchain_storage() {
|
||||
|
||||
let mut storage = InMemOffchainStorage::default();
|
||||
assert_eq!(storage.get(b"A", b"B"), None);
|
||||
assert_eq!(storage.get(b"B", b"A"), None);
|
||||
|
||||
storage.set(b"A", b"B", b"C");
|
||||
assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec()));
|
||||
assert_eq!(storage.get(b"B", b"A"), None);
|
||||
|
||||
storage.compare_and_set(b"A", b"B", Some(b"X"), b"D");
|
||||
assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec()));
|
||||
storage.compare_and_set(b"A", b"B", Some(b"C"), b"D");
|
||||
assert_eq!(storage.get(b"A", b"B"), Some(b"D".to_vec()));
|
||||
|
||||
assert!(!storage.compare_and_set(b"B", b"A", Some(b""), b"Y"));
|
||||
assert!(storage.compare_and_set(b"B", b"A", None, b"X"));
|
||||
assert_eq!(storage.get(b"B", b"A"), Some(b"X".to_vec()));
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,11 @@
|
||||
pub mod backend;
|
||||
pub mod call_executor;
|
||||
pub mod client;
|
||||
pub mod cht;
|
||||
pub mod execution_extensions;
|
||||
pub mod in_mem;
|
||||
pub mod light;
|
||||
pub mod leaves;
|
||||
pub mod notifications;
|
||||
pub mod proof_provider;
|
||||
|
||||
@@ -36,6 +39,13 @@ pub use proof_provider::*;
|
||||
|
||||
pub use sp_state_machine::{StorageProof, ExecutionStrategy, CloneableSpawn};
|
||||
|
||||
/// Usage Information Provider interface
|
||||
///
|
||||
pub trait UsageProvider<Block: sp_runtime::traits::Block> {
|
||||
/// Get usage info about current client.
|
||||
fn usage_info(&self) -> ClientInfo<Block>;
|
||||
}
|
||||
|
||||
/// Utility methods for the client.
|
||||
pub mod utils {
|
||||
use sp_blockchain::{HeaderBackend, HeaderMetadata, Error};
|
||||
|
||||
@@ -296,7 +296,25 @@ pub trait RemoteBlockchain<Block: BlockT>: Send + Sync {
|
||||
>>;
|
||||
}
|
||||
|
||||
/// Returns future that resolves header either locally, or remotely.
|
||||
pub fn future_header<Block: BlockT, F: Fetcher<Block>>(
|
||||
blockchain: &dyn RemoteBlockchain<Block>,
|
||||
fetcher: &F,
|
||||
id: BlockId<Block>,
|
||||
) -> impl Future<Output = Result<Option<Block::Header>, ClientError>> {
|
||||
use futures::future::{ready, Either, FutureExt};
|
||||
|
||||
match blockchain.header(id) {
|
||||
Ok(LocalOrRemote::Remote(request)) => Either::Left(
|
||||
fetcher
|
||||
.remote_header(request)
|
||||
.then(|header| ready(header.map(Some)))
|
||||
),
|
||||
Ok(LocalOrRemote::Unknown) => Either::Right(ready(Ok(None))),
|
||||
Ok(LocalOrRemote::Local(local_header)) => Either::Right(ready(Ok(Some(local_header)))),
|
||||
Err(err) => Either::Right(ready(Err(err))),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
|
||||
@@ -267,7 +267,7 @@ macro_rules! substrate_cli_subcommands {
|
||||
}
|
||||
|
||||
fn execution_strategies(&self, is_dev: bool)
|
||||
-> $crate::Result<::sc_service::config::ExecutionStrategies> {
|
||||
-> $crate::Result<::sc_client_api::execution_extensions::ExecutionStrategies> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.execution_strategies(is_dev)),*
|
||||
}
|
||||
|
||||
@@ -25,10 +25,11 @@ use crate::arg_enums::Database;
|
||||
use app_dirs::{AppDataType, AppInfo};
|
||||
use names::{Generator, Name};
|
||||
use sc_service::config::{
|
||||
Configuration, DatabaseConfig, ExecutionStrategies, ExtTransport, KeystoreConfig,
|
||||
NetworkConfiguration, NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode,
|
||||
Role, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod,
|
||||
WasmExecutionMethod, Role, OffchainWorkerConfig,
|
||||
Configuration, DatabaseConfig, ExtTransport, KeystoreConfig, NetworkConfiguration,
|
||||
NodeKeyConfig, PrometheusConfig, PruningMode, TelemetryEndpoints, TransactionPoolOptions,
|
||||
};
|
||||
use sc_client_api::execution_extensions::ExecutionStrategies;
|
||||
use sc_service::{ChainSpec, TracingReceiver};
|
||||
use std::future::Future;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
@@ -16,7 +16,6 @@ sp-application-crypto = { version = "2.0.0-dev", path = "../../../primitives/app
|
||||
sp-consensus-aura = { version = "0.8.0-dev", path = "../../../primitives/consensus/aura" }
|
||||
sp-block-builder = { version = "2.0.0-dev", path = "../../../primitives/block-builder" }
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "../../../client/block-builder" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../api" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0" }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" }
|
||||
@@ -42,7 +41,7 @@ sp-keyring = { version = "2.0.0-dev", path = "../../../primitives/keyring" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "../../executor" }
|
||||
sc-network = { version = "0.8.0-dev", path = "../../network" }
|
||||
sc-network-test = { version = "0.8.0-dev", path = "../../network/test" }
|
||||
sc-service = { version = "0.8.0-dev", path = "../../service" }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, path = "../../service" }
|
||||
substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" }
|
||||
env_logger = "0.7.0"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
@@ -46,8 +46,7 @@ use sp_consensus::{
|
||||
use sp_consensus::import_queue::{
|
||||
Verifier, BasicQueue, BoxJustificationImport, BoxFinalityProofImport,
|
||||
};
|
||||
use sc_client_api::backend::AuxStore;
|
||||
use sc_client::BlockOf;
|
||||
use sc_client_api::{backend::AuxStore, BlockOf};
|
||||
use sp_blockchain::{
|
||||
self, Result as CResult, well_known_cache_keys::{self, Id as CacheKeyId},
|
||||
ProvideCache, HeaderBackend,
|
||||
@@ -831,14 +830,14 @@ mod tests {
|
||||
use sc_network::config::ProtocolConfig;
|
||||
use parking_lot::Mutex;
|
||||
use sp_keyring::sr25519::Keyring;
|
||||
use sc_client::BlockchainEvents;
|
||||
use sc_client_api::BlockchainEvents;
|
||||
use sp_consensus_aura::sr25519::AuthorityPair;
|
||||
use std::task::Poll;
|
||||
use sc_block_builder::BlockBuilderProvider;
|
||||
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
type TestClient = sc_client::Client<
|
||||
type TestClient = substrate_test_runtime_client::client::Client<
|
||||
substrate_test_runtime_client::Backend,
|
||||
substrate_test_runtime_client::Executor,
|
||||
TestBlock,
|
||||
|
||||
@@ -28,7 +28,6 @@ sp-timestamp = { version = "2.0.0-dev", path = "../../../primitives/timestamp" }
|
||||
sc-telemetry = { version = "2.0.0-dev", path = "../../telemetry" }
|
||||
sc-keystore = { version = "2.0.0-dev", path = "../../keystore" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../api" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../" }
|
||||
sc-consensus-epochs = { version = "0.8.0-dev", path = "../epochs" }
|
||||
sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" }
|
||||
sp-block-builder = { version = "2.0.0-dev", path = "../../../primitives/block-builder" }
|
||||
@@ -54,7 +53,7 @@ sp-keyring = { version = "2.0.0-dev", path = "../../../primitives/keyring" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "../../executor" }
|
||||
sc-network = { version = "0.8.0-dev", path = "../../network" }
|
||||
sc-network-test = { version = "0.8.0-dev", path = "../../network/test" }
|
||||
sc-service = { version = "0.8.0-dev", path = "../../service" }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, path = "../../service" }
|
||||
substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" }
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "../../block-builder" }
|
||||
env_logger = "0.7.0"
|
||||
|
||||
@@ -40,7 +40,7 @@ type Item = DigestItem<Hash>;
|
||||
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
type TestClient = sc_client::Client<
|
||||
type TestClient = substrate_test_runtime_client::client::Client<
|
||||
substrate_test_runtime_client::Backend,
|
||||
substrate_test_runtime_client::Executor,
|
||||
TestBlock,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "sc-consensus"
|
||||
version = "0.8.0-dev"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
license = "GPL-3.0"
|
||||
homepage = "https://substrate.dev"
|
||||
repository = "https://github.com/paritytech/substrate/"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../api" }
|
||||
sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" }
|
||||
sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" }
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Collection of consensus specific imlementations
|
||||
mod longest_chain;
|
||||
|
||||
pub use longest_chain::LongestChain;
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Longest chain implementation
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::marker::PhantomData;
|
||||
use sc_client_api::backend;
|
||||
use sp_consensus::{SelectChain, Error as ConsensusError};
|
||||
use sp_blockchain::{Backend, HeaderBackend};
|
||||
use sp_runtime::{
|
||||
traits::{NumberFor, Block as BlockT},
|
||||
generic::BlockId,
|
||||
};
|
||||
|
||||
/// Implement Longest Chain Select implementation
|
||||
/// where 'longest' is defined as the highest number of blocks
|
||||
pub struct LongestChain<B, Block> {
|
||||
backend: Arc<B>,
|
||||
_phantom: PhantomData<Block>
|
||||
}
|
||||
|
||||
impl<B, Block> Clone for LongestChain<B, Block> {
|
||||
fn clone(&self) -> Self {
|
||||
let backend = self.backend.clone();
|
||||
LongestChain {
|
||||
backend,
|
||||
_phantom: Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, Block> LongestChain<B, Block>
|
||||
where
|
||||
B: backend::Backend<Block>,
|
||||
Block: BlockT,
|
||||
{
|
||||
/// Instantiate a new LongestChain for Backend B
|
||||
pub fn new(backend: Arc<B>) -> Self {
|
||||
LongestChain {
|
||||
backend,
|
||||
_phantom: Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn best_block_header(&self) -> sp_blockchain::Result<<Block as BlockT>::Header> {
|
||||
let info = self.backend.blockchain().info();
|
||||
let import_lock = self.backend.get_import_lock();
|
||||
let best_hash = self.backend
|
||||
.blockchain()
|
||||
.best_containing(info.best_hash, None, import_lock)?
|
||||
.unwrap_or(info.best_hash);
|
||||
|
||||
Ok(self.backend.blockchain().header(BlockId::Hash(best_hash))?
|
||||
.expect("given block hash was fetched from block in db; qed"))
|
||||
}
|
||||
|
||||
fn leaves(&self) -> Result<Vec<<Block as BlockT>::Hash>, sp_blockchain::Error> {
|
||||
self.backend.blockchain().leaves()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, Block> SelectChain<Block> for LongestChain<B, Block>
|
||||
where
|
||||
B: backend::Backend<Block>,
|
||||
Block: BlockT,
|
||||
{
|
||||
|
||||
fn leaves(&self) -> Result<Vec<<Block as BlockT>::Hash>, ConsensusError> {
|
||||
LongestChain::leaves(self)
|
||||
.map_err(|e| ConsensusError::ChainLookup(e.to_string()).into())
|
||||
}
|
||||
|
||||
fn best_chain(&self) -> Result<<Block as BlockT>::Header, ConsensusError>
|
||||
{
|
||||
LongestChain::best_block_header(&self)
|
||||
.map_err(|e| ConsensusError::ChainLookup(e.to_string()).into())
|
||||
}
|
||||
|
||||
fn finality_target(
|
||||
&self,
|
||||
target_hash: Block::Hash,
|
||||
maybe_max_number: Option<NumberFor<Block>>
|
||||
) -> Result<Option<Block::Hash>, ConsensusError> {
|
||||
let import_lock = self.backend.get_import_lock();
|
||||
self.backend.blockchain().best_containing(target_hash, maybe_max_number, import_lock)
|
||||
.map_err(|e| ConsensusError::ChainLookup(e.to_string()).into())
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ parking_lot = "0.10.0"
|
||||
serde = { version = "1.0", features=["derive"] }
|
||||
assert_matches = "1.3.0"
|
||||
|
||||
sc-client = { path = "../../../client" , version = "0.8.0-dev"}
|
||||
sc-client-api = { path = "../../../client/api" , version = "2.0.0-dev"}
|
||||
sc-transaction-pool = { path = "../../transaction-pool" , version = "2.0.0-dev"}
|
||||
sp-blockchain = { path = "../../../primitives/blockchain" , version = "2.0.0-dev"}
|
||||
|
||||
@@ -26,7 +26,6 @@ blake2-rfc = "0.2.18"
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../api" }
|
||||
sp-core = { version = "2.0.0-dev", path = "../../primitives/core" }
|
||||
sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../" }
|
||||
sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "../executor" }
|
||||
sc-state-db = { version = "0.8.0-dev", path = "../state-db" }
|
||||
|
||||
@@ -52,9 +52,9 @@ use std::collections::HashMap;
|
||||
|
||||
|
||||
use sc_client_api::{
|
||||
ForkBlocks, UsageInfo, MemoryInfo, BadBlocks, IoInfo, MemorySize, CloneableSpawn,
|
||||
execution_extensions::ExecutionExtensions,
|
||||
UsageInfo, MemoryInfo, IoInfo, MemorySize,
|
||||
backend::{NewBlockState, PrunableStateChangesTrieStorage},
|
||||
leaves::{LeafSet, FinalizationDisplaced},
|
||||
};
|
||||
use sp_blockchain::{
|
||||
Result as ClientResult, Error as ClientError,
|
||||
@@ -65,17 +65,13 @@ use hash_db::Prefix;
|
||||
use sp_trie::{MemoryDB, PrefixedMemoryDB, prefixed_key};
|
||||
use sp_database::Transaction;
|
||||
use parking_lot::RwLock;
|
||||
use sp_core::{ChangesTrieConfiguration, traits::CodeExecutor};
|
||||
use sp_core::offchain::storage::{OffchainOverlayedChange,OffchainOverlayedChanges};
|
||||
use sp_core::ChangesTrieConfiguration;
|
||||
use sp_core::offchain::storage::{OffchainOverlayedChange, OffchainOverlayedChanges};
|
||||
use sp_core::storage::{well_known_keys, ChildInfo};
|
||||
use sp_runtime::{
|
||||
generic::BlockId, Justification, Storage,
|
||||
BuildStorage,
|
||||
};
|
||||
use sp_runtime::{generic::BlockId, Justification, Storage};
|
||||
use sp_runtime::traits::{
|
||||
Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion, HashFor,
|
||||
};
|
||||
use sc_executor::RuntimeInfo;
|
||||
use sp_state_machine::{
|
||||
DBValue, ChangesTrieTransaction, ChangesTrieCacheAction, UsageInfo as StateUsageInfo,
|
||||
StorageCollection, ChildStorageCollection,
|
||||
@@ -83,13 +79,11 @@ use sp_state_machine::{
|
||||
};
|
||||
use crate::utils::{DatabaseType, Meta, meta_keys, read_db, read_meta};
|
||||
use crate::changes_tries_storage::{DbChangesTrieStorage, DbChangesTrieStorageTransaction};
|
||||
use sc_client::leaves::{LeafSet, FinalizationDisplaced};
|
||||
use sc_state_db::StateDb;
|
||||
use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache};
|
||||
use crate::storage_cache::{CachingState, SyncingCachingState, SharedCache, new_shared_cache};
|
||||
use crate::stats::StateUsageStats;
|
||||
use log::{trace, debug, warn};
|
||||
use prometheus_endpoint::Registry;
|
||||
|
||||
// Re-export the Database trait so that one can pass an implementation of it.
|
||||
pub use sp_database::Database;
|
||||
@@ -98,7 +92,6 @@ pub use sc_state_db::PruningMode;
|
||||
#[cfg(any(feature = "kvdb-rocksdb", test))]
|
||||
pub use bench::BenchmarkingState;
|
||||
|
||||
const CANONICALIZATION_DELAY: u64 = 4096;
|
||||
const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR: u32 = 32768;
|
||||
|
||||
/// Default value for storage cache child ratio.
|
||||
@@ -324,49 +317,6 @@ impl DatabaseSettingsSrc {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an instance of db-backed client.
|
||||
pub fn new_client<E, Block, RA>(
|
||||
settings: DatabaseSettings,
|
||||
executor: E,
|
||||
genesis_storage: &dyn BuildStorage,
|
||||
fork_blocks: ForkBlocks<Block>,
|
||||
bad_blocks: BadBlocks<Block>,
|
||||
execution_extensions: ExecutionExtensions<Block>,
|
||||
spawn_handle: Box<dyn CloneableSpawn>,
|
||||
prometheus_registry: Option<Registry>,
|
||||
config: sc_client::ClientConfig,
|
||||
) -> Result<(
|
||||
sc_client::Client<
|
||||
Backend<Block>,
|
||||
sc_client::LocalCallExecutor<Backend<Block>, E>,
|
||||
Block,
|
||||
RA,
|
||||
>,
|
||||
Arc<Backend<Block>>,
|
||||
),
|
||||
sp_blockchain::Error,
|
||||
>
|
||||
where
|
||||
Block: BlockT,
|
||||
E: CodeExecutor + RuntimeInfo,
|
||||
{
|
||||
let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?);
|
||||
let executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, spawn_handle, config.clone());
|
||||
Ok((
|
||||
sc_client::Client::new(
|
||||
backend.clone(),
|
||||
executor,
|
||||
genesis_storage,
|
||||
fork_blocks,
|
||||
bad_blocks,
|
||||
execution_extensions,
|
||||
prometheus_registry,
|
||||
config,
|
||||
)?,
|
||||
backend,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) mod columns {
|
||||
pub const META: u32 = crate::utils::COLUMN_META;
|
||||
pub const STATE: u32 = 1;
|
||||
@@ -446,14 +396,14 @@ impl<Block: BlockT> BlockchainDb<Block> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> sc_client::blockchain::HeaderBackend<Block> for BlockchainDb<Block> {
|
||||
impl<Block: BlockT> sc_client_api::blockchain::HeaderBackend<Block> for BlockchainDb<Block> {
|
||||
fn header(&self, id: BlockId<Block>) -> ClientResult<Option<Block::Header>> {
|
||||
utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id)
|
||||
}
|
||||
|
||||
fn info(&self) -> sc_client::blockchain::Info<Block> {
|
||||
fn info(&self) -> sc_client_api::blockchain::Info<Block> {
|
||||
let meta = self.meta.read();
|
||||
sc_client::blockchain::Info {
|
||||
sc_client_api::blockchain::Info {
|
||||
best_hash: meta.best_hash,
|
||||
best_number: meta.best_number,
|
||||
genesis_hash: meta.genesis_hash,
|
||||
@@ -463,7 +413,7 @@ impl<Block: BlockT> sc_client::blockchain::HeaderBackend<Block> for BlockchainDb
|
||||
}
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId<Block>) -> ClientResult<sc_client::blockchain::BlockStatus> {
|
||||
fn status(&self, id: BlockId<Block>) -> ClientResult<sc_client_api::blockchain::BlockStatus> {
|
||||
let exists = match id {
|
||||
BlockId::Hash(_) => read_db(
|
||||
&*self.db,
|
||||
@@ -474,8 +424,8 @@ impl<Block: BlockT> sc_client::blockchain::HeaderBackend<Block> for BlockchainDb
|
||||
BlockId::Number(n) => n <= self.meta.read().best_number,
|
||||
};
|
||||
match exists {
|
||||
true => Ok(sc_client::blockchain::BlockStatus::InChain),
|
||||
false => Ok(sc_client::blockchain::BlockStatus::Unknown),
|
||||
true => Ok(sc_client_api::blockchain::BlockStatus::InChain),
|
||||
false => Ok(sc_client_api::blockchain::BlockStatus::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,7 +441,7 @@ impl<Block: BlockT> sc_client::blockchain::HeaderBackend<Block> for BlockchainDb
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> sc_client::blockchain::Backend<Block> for BlockchainDb<Block> {
|
||||
impl<Block: BlockT> sc_client_api::blockchain::Backend<Block> for BlockchainDb<Block> {
|
||||
fn body(&self, id: BlockId<Block>) -> ClientResult<Option<Vec<Block::Extrinsic>>> {
|
||||
match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? {
|
||||
Some(body) => match Decode::decode(&mut &body[..]) {
|
||||
@@ -520,7 +470,7 @@ impl<Block: BlockT> sc_client::blockchain::Backend<Block> for BlockchainDb<Block
|
||||
Ok(self.meta.read().finalized_hash.clone())
|
||||
}
|
||||
|
||||
fn cache(&self) -> Option<Arc<dyn sc_client::blockchain::Cache<Block>>> {
|
||||
fn cache(&self) -> Option<Arc<dyn sc_client_api::blockchain::Cache<Block>>> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -533,8 +483,8 @@ impl<Block: BlockT> sc_client::blockchain::Backend<Block> for BlockchainDb<Block
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> sc_client::blockchain::ProvideCache<Block> for BlockchainDb<Block> {
|
||||
fn cache(&self) -> Option<Arc<dyn sc_client::blockchain::Cache<Block>>> {
|
||||
impl<Block: BlockT> sc_client_api::blockchain::ProvideCache<Block> for BlockchainDb<Block> {
|
||||
fn cache(&self) -> Option<Arc<dyn sc_client_api::blockchain::Cache<Block>>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -1035,7 +985,7 @@ impl<Block: BlockT> Backend<Block> {
|
||||
let hash = if new_canonical == number_u64 {
|
||||
hash
|
||||
} else {
|
||||
::sc_client::blockchain::HeaderBackend::hash(&self.blockchain, new_canonical.saturated_into())?
|
||||
::sc_client_api::blockchain::HeaderBackend::hash(&self.blockchain, new_canonical.saturated_into())?
|
||||
.expect("existence of block with number `new_canonical` \
|
||||
implies existence of blocks with all numbers before it; qed")
|
||||
};
|
||||
@@ -1259,7 +1209,7 @@ impl<Block: BlockT> Backend<Block> {
|
||||
};
|
||||
|
||||
let cache_update = if let Some(set_head) = operation.set_head {
|
||||
if let Some(header) = sc_client::blockchain::HeaderBackend::header(&self.blockchain, set_head)? {
|
||||
if let Some(header) = sc_client_api::blockchain::HeaderBackend::header(&self.blockchain, set_head)? {
|
||||
let number = header.number();
|
||||
let hash = header.hash();
|
||||
|
||||
@@ -1604,7 +1554,7 @@ impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
|
||||
}
|
||||
|
||||
fn state_at(&self, block: BlockId<Block>) -> ClientResult<Self::State> {
|
||||
use sc_client::blockchain::HeaderBackend as BcHeaderBackend;
|
||||
use sc_client_api::blockchain::HeaderBackend as BcHeaderBackend;
|
||||
|
||||
// special case for genesis initialization
|
||||
match block {
|
||||
@@ -1705,7 +1655,7 @@ pub(crate) mod tests {
|
||||
use crate::columns;
|
||||
use sp_core::H256;
|
||||
use sc_client_api::backend::{Backend as BTrait, BlockImportOperation as Op};
|
||||
use sc_client::blockchain::Backend as BLBTrait;
|
||||
use sc_client_api::blockchain::Backend as BLBTrait;
|
||||
use sp_runtime::testing::{Header, Block as RawBlock, ExtrinsicWrapper};
|
||||
use sp_runtime::traits::{Hash, BlakeTwo256};
|
||||
use sp_runtime::generic::DigestItem;
|
||||
@@ -2284,7 +2234,7 @@ pub(crate) mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_finalize_block_with_justification() {
|
||||
use sc_client::blockchain::{Backend as BlockChainBackend};
|
||||
use sc_client_api::blockchain::{Backend as BlockChainBackend};
|
||||
|
||||
let backend = Backend::<Block>::new_test(10, 10);
|
||||
|
||||
|
||||
@@ -20,11 +20,13 @@ use std::{sync::Arc, collections::HashMap};
|
||||
use std::convert::TryInto;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use sc_client_api::{backend::{AuxStore, NewBlockState}, UsageInfo};
|
||||
use sc_client::blockchain::{
|
||||
BlockStatus, Cache as BlockchainCache,Info as BlockchainInfo,
|
||||
use sc_client_api::{
|
||||
cht, backend::{AuxStore, NewBlockState}, UsageInfo,
|
||||
blockchain::{
|
||||
BlockStatus, Cache as BlockchainCache, Info as BlockchainInfo,
|
||||
},
|
||||
Storage
|
||||
};
|
||||
use sc_client::cht;
|
||||
use sp_blockchain::{
|
||||
CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache,
|
||||
Error as ClientError, Result as ClientResult,
|
||||
@@ -32,7 +34,6 @@ use sp_blockchain::{
|
||||
well_known_cache_keys,
|
||||
};
|
||||
use sp_database::{Database, Transaction};
|
||||
use sc_client::light::blockchain::Storage as LightBlockchainStorage;
|
||||
use codec::{Decode, Encode};
|
||||
use sp_runtime::generic::{DigestItem, BlockId};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor, HashFor};
|
||||
@@ -406,7 +407,7 @@ impl<Block> AuxStore for LightStorage<Block>
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block> LightBlockchainStorage<Block> for LightStorage<Block>
|
||||
impl<Block> Storage<Block> for LightStorage<Block>
|
||||
where Block: BlockT,
|
||||
{
|
||||
fn import_header(
|
||||
@@ -614,7 +615,7 @@ fn cht_key<N: TryInto<u32>>(cht_type: u8, block: N) -> ClientResult<[u8; 5]> {
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use sc_client::cht;
|
||||
use sc_client_api::cht;
|
||||
use sp_core::ChangesTrieConfiguration;
|
||||
use sp_runtime::generic::{DigestItem, ChangesTrieSignal};
|
||||
use sp_runtime::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper};
|
||||
|
||||
@@ -26,13 +26,13 @@ sp-arithmetic = { version = "2.0.0-dev", path = "../../primitives/arithmetic" }
|
||||
sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" }
|
||||
sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" }
|
||||
sc-consensus = { version = "0.8.0-dev", path = "../../client/consensus/common" }
|
||||
sp-core = { version = "2.0.0-dev", path = "../../primitives/core" }
|
||||
sp-api = { version = "2.0.0-dev", path = "../../primitives/api" }
|
||||
sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" }
|
||||
sc-keystore = { version = "2.0.0-dev", path = "../keystore" }
|
||||
serde_json = "1.0.41"
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../api" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../" }
|
||||
sp-inherents = { version = "2.0.0-dev", path = "../../primitives/inherents" }
|
||||
sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" }
|
||||
sc-network = { version = "0.8.0-dev", path = "../network" }
|
||||
|
||||
@@ -28,8 +28,7 @@ use parking_lot::RwLock;
|
||||
use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use sc_client_api::{backend::Backend, utils::is_descendent_of};
|
||||
use sc_client::apply_aux;
|
||||
use sc_client_api::{backend::{Backend, apply_aux}, utils::is_descendent_of};
|
||||
use finality_grandpa::{
|
||||
BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState,
|
||||
voter, voter_set::VoterSet,
|
||||
|
||||
@@ -596,7 +596,7 @@ impl<Block: BlockT> ProvableJustification<Block::Header> for GrandpaJustificatio
|
||||
pub(crate) mod tests {
|
||||
use substrate_test_runtime_client::runtime::{Block, Header, H256};
|
||||
use sc_client_api::NewBlockState;
|
||||
use substrate_test_runtime_client::sc_client::in_mem::Blockchain as InMemoryBlockchain;
|
||||
use sc_client_api::in_mem::Blockchain as InMemoryBlockchain;
|
||||
use super::*;
|
||||
use sp_core::crypto::Public;
|
||||
|
||||
|
||||
@@ -567,7 +567,7 @@ pub mod tests {
|
||||
use sp_consensus::{ForkChoiceStrategy, BlockImport};
|
||||
use sp_finality_grandpa::AuthorityId;
|
||||
use sp_core::{H256, crypto::Public};
|
||||
use substrate_test_runtime_client::sc_client::in_mem::Blockchain as InMemoryAuxStore;
|
||||
use sc_client_api::in_mem::Blockchain as InMemoryAuxStore;
|
||||
use substrate_test_runtime_client::runtime::{Block, Header};
|
||||
use crate::tests::TestApi;
|
||||
use crate::finality_proof::tests::TestJustification;
|
||||
|
||||
@@ -27,7 +27,6 @@ use parking_lot::Mutex;
|
||||
use futures_timer::Delay;
|
||||
use tokio::runtime::{Runtime, Handle};
|
||||
use sp_keyring::Ed25519Keyring;
|
||||
use sc_client::LongestChain;
|
||||
use sc_client_api::backend::TransactionFor;
|
||||
use sp_blockchain::Result;
|
||||
use sp_api::{ApiRef, StorageProof, ProvideRuntimeApi};
|
||||
@@ -50,6 +49,7 @@ use finality_proof::{
|
||||
};
|
||||
use consensus_changes::ConsensusChanges;
|
||||
use sc_block_builder::BlockBuilderProvider;
|
||||
use sc_consensus::LongestChain;
|
||||
|
||||
type PeerData =
|
||||
Mutex<
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Console informant. Prints sync progress and block events. Runs on the calling thread.
|
||||
|
||||
use ansi_term::Colour;
|
||||
use sc_client_api::BlockchainEvents;
|
||||
use sc_client_api::{BlockchainEvents, UsageProvider};
|
||||
use futures::prelude::*;
|
||||
use log::{info, warn, trace};
|
||||
use sp_runtime::traits::Header;
|
||||
|
||||
@@ -42,7 +42,6 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.
|
||||
prost = "0.6.1"
|
||||
rand = "0.7.2"
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "../block-builder" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../api" }
|
||||
sc-peerset = { version = "2.0.0-dev", path = "../peerset" }
|
||||
serde = { version = "1.0.101", features = ["derive"] }
|
||||
|
||||
@@ -54,8 +54,13 @@ use libp2p::{
|
||||
};
|
||||
use nohash_hasher::IntMap;
|
||||
use prost::Message;
|
||||
use sc_client::light::fetcher;
|
||||
use sc_client_api::StorageProof;
|
||||
use sc_client_api::{
|
||||
StorageProof,
|
||||
light::{
|
||||
self, RemoteReadRequest, RemoteBodyRequest, ChangesProof,
|
||||
RemoteCallRequest, RemoteChangesRequest, RemoteHeaderRequest,
|
||||
}
|
||||
};
|
||||
use sc_peerset::ReputationChange;
|
||||
use sp_core::{
|
||||
storage::{ChildInfo, ChildType,StorageKey, PrefixedStorageKey},
|
||||
@@ -193,27 +198,27 @@ pub enum Error {
|
||||
#[derive(Debug)]
|
||||
pub enum Request<B: Block> {
|
||||
Body {
|
||||
request: fetcher::RemoteBodyRequest<B::Header>,
|
||||
request: RemoteBodyRequest<B::Header>,
|
||||
sender: oneshot::Sender<Result<Vec<B::Extrinsic>, ClientError>>
|
||||
},
|
||||
Header {
|
||||
request: fetcher::RemoteHeaderRequest<B::Header>,
|
||||
request: light::RemoteHeaderRequest<B::Header>,
|
||||
sender: oneshot::Sender<Result<B::Header, ClientError>>
|
||||
},
|
||||
Read {
|
||||
request: fetcher::RemoteReadRequest<B::Header>,
|
||||
request: light::RemoteReadRequest<B::Header>,
|
||||
sender: oneshot::Sender<Result<HashMap<Vec<u8>, Option<Vec<u8>>>, ClientError>>
|
||||
},
|
||||
ReadChild {
|
||||
request: fetcher::RemoteReadChildRequest<B::Header>,
|
||||
request: light::RemoteReadChildRequest<B::Header>,
|
||||
sender: oneshot::Sender<Result<HashMap<Vec<u8>, Option<Vec<u8>>>, ClientError>>
|
||||
},
|
||||
Call {
|
||||
request: fetcher::RemoteCallRequest<B::Header>,
|
||||
request: light::RemoteCallRequest<B::Header>,
|
||||
sender: oneshot::Sender<Result<Vec<u8>, ClientError>>
|
||||
},
|
||||
Changes {
|
||||
request: fetcher::RemoteChangesRequest<B::Header>,
|
||||
request: light::RemoteChangesRequest<B::Header>,
|
||||
sender: oneshot::Sender<Result<Vec<(NumberFor<B>, u32)>, ClientError>>
|
||||
}
|
||||
}
|
||||
@@ -283,7 +288,7 @@ pub struct LightClientHandler<B: Block> {
|
||||
/// Blockchain client.
|
||||
chain: Arc<dyn Client<B>>,
|
||||
/// Verifies that received responses are correct.
|
||||
checker: Arc<dyn fetcher::FetchChecker<B>>,
|
||||
checker: Arc<dyn light::FetchChecker<B>>,
|
||||
/// Peer information (addresses, their best block, etc.)
|
||||
peers: HashMap<PeerId, PeerInfo<B>>,
|
||||
/// Futures sending back response to remote clients.
|
||||
@@ -306,7 +311,7 @@ where
|
||||
pub fn new(
|
||||
cfg: Config,
|
||||
chain: Arc<dyn Client<B>>,
|
||||
checker: Arc<dyn fetcher::FetchChecker<B>>,
|
||||
checker: Arc<dyn light::FetchChecker<B>>,
|
||||
peerset: sc_peerset::PeersetHandle,
|
||||
) -> Self {
|
||||
LightClientHandler {
|
||||
@@ -471,7 +476,7 @@ where
|
||||
}
|
||||
r
|
||||
};
|
||||
let reply = self.checker.check_changes_proof(&request, fetcher::ChangesProof {
|
||||
let reply = self.checker.check_changes_proof(&request, light::ChangesProof {
|
||||
max_block,
|
||||
proof: response.proof,
|
||||
roots,
|
||||
@@ -712,7 +717,7 @@ where
|
||||
request.last,
|
||||
error);
|
||||
|
||||
fetcher::ChangesProof::<B::Header> {
|
||||
light::ChangesProof::<B::Header> {
|
||||
max_block: Zero::zero(),
|
||||
proof: Vec::new(),
|
||||
roots: BTreeMap::new(),
|
||||
@@ -1289,6 +1294,7 @@ fn fmt_keys(first: Option<&Vec<u8>>, last: Option<&Vec<u8>>) -> String {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use async_std::task;
|
||||
use assert_matches::assert_matches;
|
||||
use codec::Encode;
|
||||
@@ -1313,8 +1319,7 @@ mod tests {
|
||||
swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters},
|
||||
yamux
|
||||
};
|
||||
use sc_client_api::StorageProof;
|
||||
use sc_client::light::fetcher;
|
||||
use sc_client_api::{StorageProof, RemoteReadChildRequest, FetchChecker};
|
||||
use sp_blockchain::{Error as ClientError};
|
||||
use sp_core::storage::ChildInfo;
|
||||
use std::{
|
||||
@@ -1358,12 +1363,12 @@ mod tests {
|
||||
_mark: std::marker::PhantomData<B>
|
||||
}
|
||||
|
||||
impl<B: BlockT> fetcher::FetchChecker<B> for DummyFetchChecker<B> {
|
||||
impl<B: BlockT> light::FetchChecker<B> for DummyFetchChecker<B> {
|
||||
fn check_header_proof(
|
||||
&self,
|
||||
_request: &fetcher::RemoteHeaderRequest<B::Header>,
|
||||
_request: &RemoteHeaderRequest<B::Header>,
|
||||
header: Option<B::Header>,
|
||||
_remote_proof: fetcher::StorageProof,
|
||||
_remote_proof: StorageProof,
|
||||
) -> Result<B::Header, ClientError> {
|
||||
match self.ok {
|
||||
true if header.is_some() => Ok(header.unwrap()),
|
||||
@@ -1373,8 +1378,8 @@ mod tests {
|
||||
|
||||
fn check_read_proof(
|
||||
&self,
|
||||
request: &fetcher::RemoteReadRequest<B::Header>,
|
||||
_: fetcher::StorageProof,
|
||||
request: &RemoteReadRequest<B::Header>,
|
||||
_: StorageProof,
|
||||
) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>, ClientError> {
|
||||
match self.ok {
|
||||
true => Ok(request.keys
|
||||
@@ -1389,8 +1394,8 @@ mod tests {
|
||||
|
||||
fn check_read_child_proof(
|
||||
&self,
|
||||
request: &fetcher::RemoteReadChildRequest<B::Header>,
|
||||
_: fetcher::StorageProof,
|
||||
request: &RemoteReadChildRequest<B::Header>,
|
||||
_: StorageProof,
|
||||
) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>, ClientError> {
|
||||
match self.ok {
|
||||
true => Ok(request.keys
|
||||
@@ -1405,8 +1410,8 @@ mod tests {
|
||||
|
||||
fn check_execution_proof(
|
||||
&self,
|
||||
_: &fetcher::RemoteCallRequest<B::Header>,
|
||||
_: fetcher::StorageProof,
|
||||
_: &RemoteCallRequest<B::Header>,
|
||||
_: StorageProof,
|
||||
) -> Result<Vec<u8>, ClientError> {
|
||||
match self.ok {
|
||||
true => Ok(vec![42]),
|
||||
@@ -1416,8 +1421,8 @@ mod tests {
|
||||
|
||||
fn check_changes_proof(
|
||||
&self,
|
||||
_: &fetcher::RemoteChangesRequest<B::Header>,
|
||||
_: fetcher::ChangesProof<B::Header>
|
||||
_: &RemoteChangesRequest<B::Header>,
|
||||
_: ChangesProof<B::Header>
|
||||
) -> Result<Vec<(NumberFor<B>, u32)>, ClientError> {
|
||||
match self.ok {
|
||||
true => Ok(vec![(100.into(), 2)]),
|
||||
@@ -1427,7 +1432,7 @@ mod tests {
|
||||
|
||||
fn check_body_proof(
|
||||
&self,
|
||||
_: &fetcher::RemoteBodyRequest<B::Header>,
|
||||
_: &RemoteBodyRequest<B::Header>,
|
||||
body: Vec<B::Extrinsic>
|
||||
) -> Result<Vec<B::Extrinsic>, ClientError> {
|
||||
match self.ok {
|
||||
@@ -1545,7 +1550,7 @@ mod tests {
|
||||
|
||||
// Issue our first request!
|
||||
let chan = oneshot::channel();
|
||||
let request = fetcher::RemoteCallRequest {
|
||||
let request = light::RemoteCallRequest {
|
||||
block: Default::default(),
|
||||
header: dummy_header(),
|
||||
method: "test".into(),
|
||||
@@ -1602,7 +1607,7 @@ mod tests {
|
||||
assert_eq!(1, behaviour.peers.len());
|
||||
|
||||
let chan = oneshot::channel();
|
||||
let request = fetcher::RemoteCallRequest {
|
||||
let request = light::RemoteCallRequest {
|
||||
block: Default::default(),
|
||||
header: dummy_header(),
|
||||
method: "test".into(),
|
||||
@@ -1677,7 +1682,7 @@ mod tests {
|
||||
assert_eq!(1, behaviour.peers.len());
|
||||
|
||||
let chan = oneshot::channel();
|
||||
let request = fetcher::RemoteCallRequest {
|
||||
let request = light::RemoteCallRequest {
|
||||
block: Default::default(),
|
||||
header: dummy_header(),
|
||||
method: "test".into(),
|
||||
@@ -1736,7 +1741,7 @@ mod tests {
|
||||
assert_eq!(4, behaviour.peers.len());
|
||||
|
||||
let mut chan = oneshot::channel();
|
||||
let request = fetcher::RemoteCallRequest {
|
||||
let request = light::RemoteCallRequest {
|
||||
block: Default::default(),
|
||||
header: dummy_header(),
|
||||
method: "test".into(),
|
||||
@@ -1852,7 +1857,7 @@ mod tests {
|
||||
#[test]
|
||||
fn receives_remote_call_response() {
|
||||
let mut chan = oneshot::channel();
|
||||
let request = fetcher::RemoteCallRequest {
|
||||
let request = light::RemoteCallRequest {
|
||||
block: Default::default(),
|
||||
header: dummy_header(),
|
||||
method: "test".into(),
|
||||
@@ -1866,7 +1871,7 @@ mod tests {
|
||||
#[test]
|
||||
fn receives_remote_read_response() {
|
||||
let mut chan = oneshot::channel();
|
||||
let request = fetcher::RemoteReadRequest {
|
||||
let request = light::RemoteReadRequest {
|
||||
header: dummy_header(),
|
||||
block: Default::default(),
|
||||
keys: vec![b":key".to_vec()],
|
||||
@@ -1880,7 +1885,7 @@ mod tests {
|
||||
fn receives_remote_read_child_response() {
|
||||
let mut chan = oneshot::channel();
|
||||
let child_info = ChildInfo::new_default(&b":child_storage:default:sub"[..]);
|
||||
let request = fetcher::RemoteReadChildRequest {
|
||||
let request = light::RemoteReadChildRequest {
|
||||
header: dummy_header(),
|
||||
block: Default::default(),
|
||||
storage_key: child_info.prefixed_storage_key(),
|
||||
@@ -1894,7 +1899,7 @@ mod tests {
|
||||
#[test]
|
||||
fn receives_remote_header_response() {
|
||||
let mut chan = oneshot::channel();
|
||||
let request = fetcher::RemoteHeaderRequest {
|
||||
let request = light::RemoteHeaderRequest {
|
||||
cht_root: Default::default(),
|
||||
block: 1,
|
||||
retry_count: None,
|
||||
@@ -1906,7 +1911,7 @@ mod tests {
|
||||
#[test]
|
||||
fn receives_remote_changes_response() {
|
||||
let mut chan = oneshot::channel();
|
||||
let request = fetcher::RemoteChangesRequest {
|
||||
let request = light::RemoteChangesRequest {
|
||||
changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange {
|
||||
zero: (0, Default::default()),
|
||||
end: None,
|
||||
@@ -1951,7 +1956,7 @@ mod tests {
|
||||
#[test]
|
||||
fn send_receive_call() {
|
||||
let chan = oneshot::channel();
|
||||
let request = fetcher::RemoteCallRequest {
|
||||
let request = light::RemoteCallRequest {
|
||||
block: Default::default(),
|
||||
header: dummy_header(),
|
||||
method: "test".into(),
|
||||
@@ -1966,7 +1971,7 @@ mod tests {
|
||||
#[test]
|
||||
fn send_receive_read() {
|
||||
let chan = oneshot::channel();
|
||||
let request = fetcher::RemoteReadRequest {
|
||||
let request = light::RemoteReadRequest {
|
||||
header: dummy_header(),
|
||||
block: Default::default(),
|
||||
keys: vec![b":key".to_vec()],
|
||||
@@ -1981,7 +1986,7 @@ mod tests {
|
||||
fn send_receive_read_child() {
|
||||
let chan = oneshot::channel();
|
||||
let child_info = ChildInfo::new_default(&b":child_storage:default:sub"[..]);
|
||||
let request = fetcher::RemoteReadChildRequest {
|
||||
let request = light::RemoteReadChildRequest {
|
||||
header: dummy_header(),
|
||||
block: Default::default(),
|
||||
storage_key: child_info.prefixed_storage_key(),
|
||||
@@ -1997,7 +2002,7 @@ mod tests {
|
||||
fn send_receive_header() {
|
||||
let _ = env_logger::try_init();
|
||||
let chan = oneshot::channel();
|
||||
let request = fetcher::RemoteHeaderRequest {
|
||||
let request = light::RemoteHeaderRequest {
|
||||
cht_root: Default::default(),
|
||||
block: 1,
|
||||
retry_count: None,
|
||||
@@ -2010,7 +2015,7 @@ mod tests {
|
||||
#[test]
|
||||
fn send_receive_changes() {
|
||||
let chan = oneshot::channel();
|
||||
let request = fetcher::RemoteChangesRequest {
|
||||
let request = light::RemoteChangesRequest {
|
||||
changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange {
|
||||
zero: (0, Default::default()),
|
||||
end: None,
|
||||
|
||||
@@ -21,7 +21,7 @@ futures-timer = "3.0.1"
|
||||
rand = "0.7.2"
|
||||
libp2p = { version = "0.18.1", default-features = false, features = ["libp2p-websocket"] }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../" }
|
||||
sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../api" }
|
||||
sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" }
|
||||
sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" }
|
||||
@@ -32,3 +32,4 @@ env_logger = "0.7.0"
|
||||
substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" }
|
||||
substrate-test-runtime = { version = "2.0.0-dev", path = "../../../test-utils/runtime" }
|
||||
tempfile = "3.1.0"
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, features = ["test-helpers"], path = "../../service" }
|
||||
|
||||
@@ -27,12 +27,16 @@ use libp2p::build_multiaddr;
|
||||
use log::trace;
|
||||
use sc_network::config::FinalityProofProvider;
|
||||
use sp_blockchain::{
|
||||
Result as ClientResult, well_known_cache_keys::{self, Id as CacheKeyId}, Info as BlockchainInfo,
|
||||
HeaderBackend, Result as ClientResult,
|
||||
well_known_cache_keys::{self, Id as CacheKeyId},
|
||||
Info as BlockchainInfo,
|
||||
};
|
||||
use sc_client_api::{BlockchainEvents, BlockImportNotification, FinalityNotifications, ImportNotifications, FinalityNotification, backend::{TransactionFor, AuxStore, Backend, Finalizer}, BlockBackend};
|
||||
use sc_client_api::{
|
||||
BlockchainEvents, BlockImportNotification, FinalityNotifications, ImportNotifications, FinalityNotification,
|
||||
backend::{TransactionFor, AuxStore, Backend, Finalizer}, BlockBackend,
|
||||
};
|
||||
use sc_consensus::LongestChain;
|
||||
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
|
||||
use sc_client::LongestChain;
|
||||
use sc_client::blockchain::HeaderBackend;
|
||||
use sc_network::config::Role;
|
||||
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
|
||||
use sp_consensus::import_queue::{
|
||||
@@ -52,7 +56,7 @@ use sp_runtime::generic::{BlockId, OpaqueDigestItemId};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
||||
use sp_runtime::Justification;
|
||||
use substrate_test_runtime_client::{self, AccountKeyring};
|
||||
|
||||
use sc_service::client::Client;
|
||||
pub use sc_network::config::EmptyTransactionPool;
|
||||
pub use substrate_test_runtime_client::runtime::{Block, Extrinsic, Hash, Transfer};
|
||||
pub use substrate_test_runtime_client::{TestClient, TestClientBuilder, TestClientBuilderExt};
|
||||
@@ -88,10 +92,18 @@ impl<B: BlockT> Verifier<B> for PassThroughVerifier {
|
||||
}
|
||||
}
|
||||
|
||||
pub type PeersFullClient =
|
||||
sc_client::Client<substrate_test_runtime_client::Backend, substrate_test_runtime_client::Executor, Block, substrate_test_runtime_client::runtime::RuntimeApi>;
|
||||
pub type PeersLightClient =
|
||||
sc_client::Client<substrate_test_runtime_client::LightBackend, substrate_test_runtime_client::LightExecutor, Block, substrate_test_runtime_client::runtime::RuntimeApi>;
|
||||
pub type PeersFullClient = Client<
|
||||
substrate_test_runtime_client::Backend,
|
||||
substrate_test_runtime_client::Executor,
|
||||
Block,
|
||||
substrate_test_runtime_client::runtime::RuntimeApi
|
||||
>;
|
||||
pub type PeersLightClient = Client<
|
||||
substrate_test_runtime_client::LightBackend,
|
||||
substrate_test_runtime_client::LightExecutor,
|
||||
Block,
|
||||
substrate_test_runtime_client::runtime::RuntimeApi
|
||||
>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum PeersClient {
|
||||
|
||||
@@ -14,7 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"]
|
||||
[dependencies]
|
||||
sc-rpc-api = { version = "0.8.0-dev", path = "../rpc-api" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../api" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../" }
|
||||
sp-api = { version = "2.0.0-dev", path = "../../primitives/api" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0" }
|
||||
futures = { version = "0.3.1", features = ["compat"] }
|
||||
|
||||
@@ -21,9 +21,7 @@ use futures::{future::ready, FutureExt, TryFutureExt};
|
||||
use rpc::futures::future::{result, Future, Either};
|
||||
|
||||
use sc_rpc_api::Subscriptions;
|
||||
use sc_client::{
|
||||
light::{fetcher::{Fetcher, RemoteBodyRequest}, blockchain::RemoteBlockchain},
|
||||
};
|
||||
use sc_client_api::light::{Fetcher, RemoteBodyRequest, RemoteBlockchain};
|
||||
use sp_runtime::{
|
||||
generic::{BlockId, SignedBlock},
|
||||
traits::{Block as BlockT},
|
||||
@@ -80,7 +78,7 @@ impl<Block, Client, F> ChainBackend<Client, Block> for LightChain<Block, Client,
|
||||
let hash = self.unwrap_or_best(hash);
|
||||
|
||||
let fetcher = self.fetcher.clone();
|
||||
let maybe_header = sc_client::light::blockchain::future_header(
|
||||
let maybe_header = sc_client_api::light::future_header(
|
||||
&*self.remote_blockchain,
|
||||
&*fetcher,
|
||||
BlockId::Hash(hash),
|
||||
|
||||
@@ -31,10 +31,7 @@ use rpc::{
|
||||
};
|
||||
|
||||
use sc_rpc_api::Subscriptions;
|
||||
use sc_client::{
|
||||
self, BlockchainEvents,
|
||||
light::{fetcher::Fetcher, blockchain::RemoteBlockchain},
|
||||
};
|
||||
use sc_client_api::{BlockchainEvents, light::{Fetcher, RemoteBlockchain}};
|
||||
use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
|
||||
use sp_rpc::{number::NumberOrHex, list::ListOrValue};
|
||||
use sp_runtime::{
|
||||
|
||||
@@ -27,7 +27,7 @@ use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
|
||||
use rpc::{Result as RpcResult, futures::{Future, future::result}};
|
||||
|
||||
use sc_rpc_api::{Subscriptions, state::ReadProof};
|
||||
use sc_client::{light::{blockchain::RemoteBlockchain, fetcher::Fetcher}};
|
||||
use sc_client_api::light::{RemoteBlockchain, Fetcher};
|
||||
use sp_core::{Bytes, storage::{StorageKey, PrefixedStorageKey, StorageData, StorageChangeSet}};
|
||||
use sp_version::RuntimeVersion;
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
|
||||
@@ -27,7 +27,7 @@ use rpc::{Result as RpcResult, futures::{stream, Future, Sink, Stream, future::r
|
||||
use sc_rpc_api::{Subscriptions, state::ReadProof};
|
||||
use sc_client_api::backend::Backend;
|
||||
use sp_blockchain::{Result as ClientResult, Error as ClientError, HeaderMetadata, CachedHeaderMetadata, HeaderBackend};
|
||||
use sc_client::BlockchainEvents;
|
||||
use sc_client_api::BlockchainEvents;
|
||||
use sp_core::{
|
||||
Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet,
|
||||
ChildInfo, ChildType, PrefixedStorageKey},
|
||||
|
||||
@@ -40,11 +40,11 @@ use rpc::{
|
||||
|
||||
use sc_rpc_api::{Subscriptions, state::ReadProof};
|
||||
use sp_blockchain::{Error as ClientError, HeaderBackend};
|
||||
use sc_client::{
|
||||
use sc_client_api::{
|
||||
BlockchainEvents,
|
||||
light::{
|
||||
blockchain::{future_header, RemoteBlockchain},
|
||||
fetcher::{Fetcher, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest},
|
||||
RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest,
|
||||
RemoteBlockchain, Fetcher, future_header,
|
||||
},
|
||||
};
|
||||
use sp_core::{
|
||||
|
||||
@@ -19,11 +19,14 @@ db = ["sc-client-db/kvdb-rocksdb", "sc-client-db/parity-db"]
|
||||
wasmtime = [
|
||||
"sc-executor/wasmtime",
|
||||
]
|
||||
# exposes the client type
|
||||
test-helpers = []
|
||||
|
||||
[dependencies]
|
||||
derive_more = "0.99.2"
|
||||
futures01 = { package = "futures", version = "0.1.29" }
|
||||
futures = "0.3.4"
|
||||
rand = "0.7.3"
|
||||
parking_lot = "0.10.0"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.8"
|
||||
@@ -32,30 +35,37 @@ futures-timer = "3.0.1"
|
||||
wasm-timer = "0.2"
|
||||
exit-future = "0.2.0"
|
||||
pin-project = "0.4.8"
|
||||
hash-db = "0.15.2"
|
||||
serde = "1.0.101"
|
||||
serde_json = "1.0.41"
|
||||
sysinfo = "0.13.3"
|
||||
sc-keystore = { version = "2.0.0-dev", path = "../keystore" }
|
||||
sp-io = { version = "2.0.0-dev", path = "../../primitives/io" }
|
||||
sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" }
|
||||
sp-trie = { version = "2.0.0-dev", path = "../../primitives/trie" }
|
||||
sp-externalities = { version = "0.8.0-dev", path = "../../primitives/externalities" }
|
||||
sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" }
|
||||
sp-version = { version = "2.0.0-dev", path = "../../primitives/version" }
|
||||
sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" }
|
||||
sp-core = { version = "2.0.0-dev", path = "../../primitives/core" }
|
||||
sp-session = { version = "2.0.0-dev", path = "../../primitives/session" }
|
||||
sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" }
|
||||
sp-application-crypto = { version = "2.0.0-dev", path = "../../primitives/application-crypto" }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" }
|
||||
sc-network = { version = "0.8.0-dev", path = "../network" }
|
||||
sc-chain-spec = { version = "2.0.0-dev", path = "../chain-spec" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../api" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../" }
|
||||
sp-api = { version = "2.0.0-dev", path = "../../primitives/api" }
|
||||
sc-client-db = { version = "0.8.0-dev", path = "../db" }
|
||||
sc-client-db = { version = "0.8.0-dev", default-features = false, path = "../db" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "../executor" }
|
||||
sc-transaction-pool = { version = "2.0.0-dev", path = "../transaction-pool" }
|
||||
sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transaction-pool" }
|
||||
sc-rpc-server = { version = "2.0.0-dev", path = "../rpc-servers" }
|
||||
sc-rpc = { version = "2.0.0-dev", path = "../rpc" }
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "../block-builder" }
|
||||
sp-block-builder = { version = "2.0.0-dev", path = "../../primitives/block-builder" }
|
||||
|
||||
sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" }
|
||||
sc-offchain = { version = "2.0.0-dev", path = "../offchain" }
|
||||
parity-multiaddr = { package = "parity-multiaddr", version = "0.7.3" }
|
||||
|
||||
@@ -20,14 +20,11 @@ use crate::status_sinks;
|
||||
use crate::config::{Configuration, KeystoreConfig, PrometheusConfig, OffchainWorkerConfig};
|
||||
use crate::metrics::MetricsService;
|
||||
use sc_client_api::{
|
||||
self,
|
||||
BlockchainEvents,
|
||||
backend::RemoteBackend, light::RemoteBlockchain,
|
||||
execution_extensions::ExtensionsFactory,
|
||||
ExecutorProvider, CallExecutor
|
||||
self, BlockchainEvents, backend::RemoteBackend, light::RemoteBlockchain, execution_extensions::ExtensionsFactory,
|
||||
ExecutorProvider, CallExecutor, ForkBlocks, BadBlocks, CloneableSpawn, UsageProvider,
|
||||
};
|
||||
use crate::client::{Client, ClientConfig};
|
||||
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
|
||||
use sc_client::{Client, ClientConfig};
|
||||
use sc_chain_spec::get_extension;
|
||||
use sp_consensus::{
|
||||
block_validation::{BlockAnnounceValidator, DefaultBlockAnnounceValidator},
|
||||
@@ -47,7 +44,7 @@ use sp_runtime::traits::{
|
||||
Block as BlockT, NumberFor, SaturatedConversion, HashFor,
|
||||
};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sc_executor::{NativeExecutor, NativeExecutionDispatch};
|
||||
use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{Read, Write, Seek},
|
||||
@@ -57,7 +54,11 @@ use wasm_timer::SystemTime;
|
||||
use sc_telemetry::{telemetry, SUBSTRATE_INFO};
|
||||
use sp_transaction_pool::{MaintainedTransactionPool, ChainEvent};
|
||||
use sp_blockchain;
|
||||
use prometheus_endpoint::Registry as PrometheusRegistry;
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_client_db::{Backend, DatabaseSettings};
|
||||
use sp_core::traits::CodeExecutor;
|
||||
use sp_runtime::BuildStorage;
|
||||
use sc_client_api::execution_extensions::ExecutionExtensions;
|
||||
|
||||
pub type BackgroundTask = Pin<Box<dyn Future<Output=()> + Send>>;
|
||||
|
||||
@@ -111,7 +112,7 @@ pub type TFullClient<TBl, TRtApi, TExecDisp> = Client<
|
||||
pub type TFullBackend<TBl> = sc_client_db::Backend<TBl>;
|
||||
|
||||
/// Full client call executor type.
|
||||
pub type TFullCallExecutor<TBl, TExecDisp> = sc_client::LocalCallExecutor<
|
||||
pub type TFullCallExecutor<TBl, TExecDisp> = crate::client::LocalCallExecutor<
|
||||
sc_client_db::Backend<TBl>,
|
||||
NativeExecutor<TExecDisp>,
|
||||
>;
|
||||
@@ -125,19 +126,19 @@ pub type TLightClient<TBl, TRtApi, TExecDisp> = Client<
|
||||
>;
|
||||
|
||||
/// Light client backend type.
|
||||
pub type TLightBackend<TBl> = sc_client::light::backend::Backend<
|
||||
pub type TLightBackend<TBl> = crate::client::light::backend::Backend<
|
||||
sc_client_db::light::LightStorage<TBl>,
|
||||
HashFor<TBl>,
|
||||
>;
|
||||
|
||||
/// Light call executor type.
|
||||
pub type TLightCallExecutor<TBl, TExecDisp> = sc_client::light::call_executor::GenesisCallExecutor<
|
||||
sc_client::light::backend::Backend<
|
||||
pub type TLightCallExecutor<TBl, TExecDisp> = crate::client::light::call_executor::GenesisCallExecutor<
|
||||
crate::client::light::backend::Backend<
|
||||
sc_client_db::light::LightStorage<TBl>,
|
||||
HashFor<TBl>
|
||||
>,
|
||||
sc_client::LocalCallExecutor<
|
||||
sc_client::light::backend::Backend<
|
||||
crate::client::LocalCallExecutor<
|
||||
crate::client::light::backend::Backend<
|
||||
sc_client_db::light::LightStorage<TBl>,
|
||||
HashFor<TBl>
|
||||
>,
|
||||
@@ -188,11 +189,11 @@ fn new_full_parts<TBl, TRtApi, TExecDisp>(
|
||||
);
|
||||
|
||||
let chain_spec = &config.chain_spec;
|
||||
let fork_blocks = get_extension::<sc_client::ForkBlocks<TBl>>(chain_spec.extensions())
|
||||
let fork_blocks = get_extension::<ForkBlocks<TBl>>(chain_spec.extensions())
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
let bad_blocks = get_extension::<sc_client::BadBlocks<TBl>>(chain_spec.extensions())
|
||||
let bad_blocks = get_extension::<BadBlocks<TBl>>(chain_spec.extensions())
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
@@ -210,7 +211,7 @@ fn new_full_parts<TBl, TRtApi, TExecDisp>(
|
||||
Some(keystore.clone()),
|
||||
);
|
||||
|
||||
sc_client_db::new_client(
|
||||
new_client(
|
||||
db_config,
|
||||
executor,
|
||||
chain_spec.as_storage_builder(),
|
||||
@@ -229,6 +230,52 @@ fn new_full_parts<TBl, TRtApi, TExecDisp>(
|
||||
Ok((client, backend, keystore, task_manager))
|
||||
}
|
||||
|
||||
|
||||
/// Create an instance of db-backed client.
|
||||
pub fn new_client<E, Block, RA>(
|
||||
settings: DatabaseSettings,
|
||||
executor: E,
|
||||
genesis_storage: &dyn BuildStorage,
|
||||
fork_blocks: ForkBlocks<Block>,
|
||||
bad_blocks: BadBlocks<Block>,
|
||||
execution_extensions: ExecutionExtensions<Block>,
|
||||
spawn_handle: Box<dyn CloneableSpawn>,
|
||||
prometheus_registry: Option<Registry>,
|
||||
config: ClientConfig,
|
||||
) -> Result<(
|
||||
crate::client::Client<
|
||||
Backend<Block>,
|
||||
crate::client::LocalCallExecutor<Backend<Block>, E>,
|
||||
Block,
|
||||
RA,
|
||||
>,
|
||||
Arc<Backend<Block>>,
|
||||
),
|
||||
sp_blockchain::Error,
|
||||
>
|
||||
where
|
||||
Block: BlockT,
|
||||
E: CodeExecutor + RuntimeInfo,
|
||||
{
|
||||
const CANONICALIZATION_DELAY: u64 = 4096;
|
||||
|
||||
let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?);
|
||||
let executor = crate::client::LocalCallExecutor::new(backend.clone(), executor, spawn_handle, config.clone());
|
||||
Ok((
|
||||
crate::client::Client::new(
|
||||
backend.clone(),
|
||||
executor,
|
||||
genesis_storage,
|
||||
fork_blocks,
|
||||
bad_blocks,
|
||||
execution_extensions,
|
||||
prometheus_registry,
|
||||
config,
|
||||
)?,
|
||||
backend,
|
||||
))
|
||||
}
|
||||
|
||||
impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> {
|
||||
/// Start the service builder with a configuration.
|
||||
pub fn new_full<TBl: BlockT, TRtApi, TExecDisp: NativeExecutionDispatch + 'static>(
|
||||
@@ -315,18 +362,18 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> {
|
||||
};
|
||||
sc_client_db::light::LightStorage::new(db_settings)?
|
||||
};
|
||||
let light_blockchain = sc_client::light::new_light_blockchain(db_storage);
|
||||
let light_blockchain = crate::client::light::new_light_blockchain(db_storage);
|
||||
let fetch_checker = Arc::new(
|
||||
sc_client::light::new_fetch_checker::<_, TBl, _>(
|
||||
crate::client::light::new_fetch_checker::<_, TBl, _>(
|
||||
light_blockchain.clone(),
|
||||
executor.clone(),
|
||||
Box::new(task_manager.spawn_handle()),
|
||||
),
|
||||
);
|
||||
let fetcher = Arc::new(sc_network::config::OnDemand::new(fetch_checker));
|
||||
let backend = sc_client::light::new_light_backend(light_blockchain);
|
||||
let backend = crate::client::light::new_light_backend(light_blockchain);
|
||||
let remote_blockchain = backend.remote_blockchain();
|
||||
let client = Arc::new(sc_client::light::new_light(
|
||||
let client = Arc::new(crate::client::light::new_light(
|
||||
backend.clone(),
|
||||
config.chain_spec.as_storage_builder(),
|
||||
executor,
|
||||
@@ -601,7 +648,7 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
|
||||
sc_transaction_pool::txpool::Options,
|
||||
Arc<TCl>,
|
||||
Option<TFchr>,
|
||||
Option<&PrometheusRegistry>,
|
||||
Option<&Registry>,
|
||||
) -> Result<(UExPool, Option<BackgroundTask>), Error>
|
||||
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp,
|
||||
UExPool, TRpc, Backend>, Error>
|
||||
@@ -757,7 +804,7 @@ ServiceBuilder<
|
||||
TBl: BlockT,
|
||||
TRtApi: 'static + Send + Sync,
|
||||
TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
|
||||
TExec: 'static + sc_client::CallExecutor<TBl> + Send + Sync + Clone,
|
||||
TExec: 'static + CallExecutor<TBl> + Send + Sync + Clone,
|
||||
TSc: Clone,
|
||||
TImpQu: 'static + ImportQueue<TBl>,
|
||||
TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> + MallocSizeOfWasm + 'static,
|
||||
|
||||
@@ -27,7 +27,7 @@ use sp_runtime::traits::{
|
||||
};
|
||||
use sp_runtime::generic::{BlockId, SignedBlock};
|
||||
use codec::{Decode, Encode, IoReader};
|
||||
use sc_client::{Client, LocalCallExecutor};
|
||||
use crate::client::{Client, LocalCallExecutor};
|
||||
use sp_consensus::{
|
||||
BlockOrigin,
|
||||
import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue},
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ use sp_externalities::Extensions;
|
||||
use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor, offchain::storage::OffchainOverlayedChanges};
|
||||
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
|
||||
use sc_client_api::{backend, call_executor::CallExecutor, CloneableSpawn};
|
||||
use crate::client::ClientConfig;
|
||||
use super::client::ClientConfig;
|
||||
|
||||
/// Call executor that executes methods locally, querying all required
|
||||
/// data from local backend.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Tool for creating the genesis block.
|
||||
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, Zero};
|
||||
|
||||
/// Create a genesis block, given the initial storage.
|
||||
pub fn construct_genesis_block<
|
||||
Block: BlockT
|
||||
> (
|
||||
state_root: Block::Hash
|
||||
) -> Block {
|
||||
let extrinsics_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||
Vec::new(),
|
||||
);
|
||||
|
||||
Block::new(
|
||||
<<Block as BlockT>::Header as HeaderT>::new(
|
||||
Zero::zero(),
|
||||
extrinsics_root,
|
||||
state_root,
|
||||
Default::default(),
|
||||
Default::default()
|
||||
),
|
||||
Default::default()
|
||||
)
|
||||
}
|
||||
+3
-53
@@ -32,7 +32,6 @@ use sp_state_machine::{
|
||||
};
|
||||
use sp_runtime::{generic::BlockId, Justification, Storage};
|
||||
use sp_runtime::traits::{Block as BlockT, NumberFor, Zero, Header, HashFor};
|
||||
use crate::in_mem::check_genesis_storage;
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
use sc_client_api::{
|
||||
backend::{
|
||||
@@ -43,9 +42,10 @@ use sc_client_api::{
|
||||
HeaderBackend as BlockchainHeaderBackend, well_known_cache_keys,
|
||||
},
|
||||
light::Storage as BlockchainStorage,
|
||||
in_mem::check_genesis_storage,
|
||||
UsageInfo,
|
||||
};
|
||||
use crate::light::blockchain::Blockchain;
|
||||
use super::blockchain::Blockchain;
|
||||
use hash_db::Hasher;
|
||||
|
||||
const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always succeeds; qed";
|
||||
@@ -251,7 +251,7 @@ where
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn remote_blockchain(&self) -> Arc<dyn crate::light::blockchain::RemoteBlockchain<Block>> {
|
||||
fn remote_blockchain(&self) -> Arc<dyn super::blockchain::RemoteBlockchain<Block>> {
|
||||
self.blockchain.clone()
|
||||
}
|
||||
}
|
||||
@@ -513,53 +513,3 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use substrate_test_runtime_client::{self, runtime::Block};
|
||||
use sc_client_api::backend::NewBlockState;
|
||||
use crate::light::blockchain::tests::{DummyBlockchain, DummyStorage};
|
||||
use sp_runtime::traits::BlakeTwo256;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn local_state_is_created_when_genesis_state_is_available() {
|
||||
let def = Default::default();
|
||||
let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default());
|
||||
|
||||
let backend: Backend<_, BlakeTwo256> = Backend::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
);
|
||||
let mut op = backend.begin_operation().unwrap();
|
||||
op.set_block_data(header0, None, None, NewBlockState::Final).unwrap();
|
||||
op.reset_storage(Default::default()).unwrap();
|
||||
backend.commit_operation(op).unwrap();
|
||||
|
||||
match backend.state_at(BlockId::Number(0)).unwrap() {
|
||||
GenesisOrUnavailableState::Genesis(_) => (),
|
||||
_ => panic!("unexpected state"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unavailable_state_is_created_when_genesis_state_is_unavailable() {
|
||||
let backend: Backend<_, BlakeTwo256> = Backend::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
);
|
||||
|
||||
match backend.state_at(BlockId::Number(0)).unwrap() {
|
||||
GenesisOrUnavailableState::Unavailable => (),
|
||||
_ => panic!("unexpected state"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn light_aux_store_is_updated_via_non_importing_op() {
|
||||
let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new())));
|
||||
let mut op = ClientBackend::<Block>::begin_operation(&backend).unwrap();
|
||||
BlockImportOperation::<Block>::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap();
|
||||
ClientBackend::<Block>::commit_operation(&backend, op).unwrap();
|
||||
|
||||
assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2]));
|
||||
}
|
||||
}
|
||||
+3
-155
@@ -17,7 +17,6 @@
|
||||
//! Light client blockchain backend. Only stores headers and justifications of recent
|
||||
//! blocks. CHT roots are stored for headers of ancient blocks.
|
||||
|
||||
use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
|
||||
use sp_runtime::{Justification, generic::BlockId};
|
||||
@@ -38,10 +37,10 @@ pub use sc_client_api::{
|
||||
},
|
||||
light::{
|
||||
RemoteBlockchain, LocalOrRemote, Storage
|
||||
}
|
||||
},
|
||||
cht,
|
||||
};
|
||||
use crate::cht;
|
||||
use crate::light::fetcher::{Fetcher, RemoteHeaderRequest};
|
||||
use super::fetcher::RemoteHeaderRequest;
|
||||
|
||||
/// Light client blockchain.
|
||||
pub struct Blockchain<S> {
|
||||
@@ -173,154 +172,3 @@ impl<S, Block: BlockT> RemoteBlockchain<Block> for Blockchain<S>
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns future that resolves header either locally, or remotely.
|
||||
pub fn future_header<Block: BlockT, F: Fetcher<Block>>(
|
||||
blockchain: &dyn RemoteBlockchain<Block>,
|
||||
fetcher: &F,
|
||||
id: BlockId<Block>,
|
||||
) -> impl Future<Output = Result<Option<Block::Header>, ClientError>> {
|
||||
use futures::future::{ready, Either, FutureExt};
|
||||
|
||||
match blockchain.header(id) {
|
||||
Ok(LocalOrRemote::Remote(request)) => Either::Left(
|
||||
fetcher
|
||||
.remote_header(request)
|
||||
.then(|header| ready(header.map(Some)))
|
||||
),
|
||||
Ok(LocalOrRemote::Unknown) => Either::Right(ready(Ok(None))),
|
||||
Ok(LocalOrRemote::Local(local_header)) => Either::Right(ready(Ok(Some(local_header)))),
|
||||
Err(err) => Either::Right(ready(Err(err))),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use std::collections::HashMap;
|
||||
use parking_lot::Mutex;
|
||||
use substrate_test_runtime_client::runtime::{Hash, Block, Header};
|
||||
use sc_client_api::blockchain::Info;
|
||||
use super::*;
|
||||
|
||||
pub type DummyBlockchain = Blockchain<DummyStorage>;
|
||||
|
||||
pub struct DummyStorage {
|
||||
pub changes_tries_cht_roots: HashMap<u64, Hash>,
|
||||
pub aux_store: Mutex<HashMap<Vec<u8>, Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl DummyStorage {
|
||||
pub fn new() -> Self {
|
||||
DummyStorage {
|
||||
changes_tries_cht_roots: HashMap::new(),
|
||||
aux_store: Mutex::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockchainHeaderBackend<Block> for DummyStorage {
|
||||
fn header(&self, _id: BlockId<Block>) -> ClientResult<Option<Header>> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn info(&self) -> Info<Block> {
|
||||
panic!("Test error")
|
||||
}
|
||||
|
||||
fn status(&self, _id: BlockId<Block>) -> ClientResult<BlockStatus> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn number(&self, hash: Hash) -> ClientResult<Option<NumberFor<Block>>> {
|
||||
if hash == Default::default() {
|
||||
Ok(Some(Default::default()))
|
||||
} else {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self, number: u64) -> ClientResult<Option<Hash>> {
|
||||
if number == 0 {
|
||||
Ok(Some(Default::default()))
|
||||
} else {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HeaderMetadata<Block> for DummyStorage {
|
||||
type Error = ClientError;
|
||||
|
||||
fn header_metadata(&self, hash: Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
|
||||
self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header))
|
||||
.ok_or(ClientError::UnknownBlock("header not found".to_owned()))
|
||||
}
|
||||
fn insert_header_metadata(&self, _hash: Hash, _metadata: CachedHeaderMetadata<Block>) {}
|
||||
fn remove_header_metadata(&self, _hash: Hash) {}
|
||||
}
|
||||
|
||||
impl AuxStore for DummyStorage {
|
||||
fn insert_aux<
|
||||
'a,
|
||||
'b: 'a,
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
>(&self, insert: I, _delete: D) -> ClientResult<()> {
|
||||
for (k, v) in insert.into_iter() {
|
||||
self.aux_store.lock().insert(k.to_vec(), v.to_vec());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_aux(&self, key: &[u8]) -> ClientResult<Option<Vec<u8>>> {
|
||||
Ok(self.aux_store.lock().get(key).cloned())
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage<Block> for DummyStorage {
|
||||
fn import_header(
|
||||
&self,
|
||||
_header: Header,
|
||||
_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
|
||||
_state: NewBlockState,
|
||||
_aux_ops: Vec<(Vec<u8>, Option<Vec<u8>>)>,
|
||||
) -> ClientResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_head(&self, _block: BlockId<Block>) -> ClientResult<()> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn finalize_header(&self, _block: BlockId<Block>) -> ClientResult<()> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn last_finalized(&self) -> ClientResult<Hash> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn header_cht_root(&self, _cht_size: u64, _block: u64) -> ClientResult<Option<Hash>> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn changes_trie_cht_root(&self, cht_size: u64, block: u64) -> ClientResult<Option<Hash>> {
|
||||
cht::block_to_cht_number(cht_size, block)
|
||||
.and_then(|cht_num| self.changes_tries_cht_roots.get(&cht_num))
|
||||
.cloned()
|
||||
.ok_or_else(|| ClientError::Backend(
|
||||
format!("Test error: CHT for block #{} not found", block)
|
||||
).into())
|
||||
.map(Some)
|
||||
}
|
||||
|
||||
fn cache(&self) -> Option<Arc<dyn BlockchainCache<Block>>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn usage_info(&self) -> Option<sc_client_api::UsageInfo> {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-231
@@ -243,7 +243,11 @@ pub fn check_execution_proof<Header, E, H>(
|
||||
)
|
||||
}
|
||||
|
||||
fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Header) -> Header>(
|
||||
/// Check remote contextual execution proof using given backend and header factory.
|
||||
///
|
||||
/// Method is executed using passed header as environment' current block.
|
||||
/// Proof should include both environment preparation proof and method execution proof.
|
||||
pub fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader>(
|
||||
executor: &E,
|
||||
spawn_handle: Box<dyn CloneableSpawn>,
|
||||
request: &RemoteCallRequest<Header>,
|
||||
@@ -251,10 +255,11 @@ fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Head
|
||||
make_next_header: MakeNextHeader,
|
||||
) -> ClientResult<Vec<u8>>
|
||||
where
|
||||
Header: HeaderT,
|
||||
E: CodeExecutor + Clone + 'static,
|
||||
H: Hasher,
|
||||
Header: HeaderT,
|
||||
H::Out: Ord + codec::Codec + 'static,
|
||||
MakeNextHeader: Fn(&Header) -> Header,
|
||||
{
|
||||
let local_state_root = request.header.state_root();
|
||||
let root: H::Out = convert_hash(&local_state_root);
|
||||
@@ -290,232 +295,3 @@ fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Head
|
||||
)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_consensus::BlockOrigin;
|
||||
use substrate_test_runtime_client::{
|
||||
runtime::{Header, Digest, Block}, TestClient, ClientBlockImportExt,
|
||||
};
|
||||
use sc_executor::{NativeExecutor, WasmExecutionMethod};
|
||||
use sp_core::{H256, tasks::executor as tasks_executor};
|
||||
use sc_client_api::backend::{Backend, NewBlockState};
|
||||
use crate::in_mem::Backend as InMemBackend;
|
||||
use sc_client_api::ProofProvider;
|
||||
use sp_runtime::traits::BlakeTwo256;
|
||||
use sc_block_builder::BlockBuilderProvider;
|
||||
|
||||
struct DummyCallExecutor;
|
||||
|
||||
impl CallExecutor<Block> for DummyCallExecutor {
|
||||
type Error = ClientError;
|
||||
|
||||
type Backend = substrate_test_runtime_client::Backend;
|
||||
|
||||
fn call(
|
||||
&self,
|
||||
_id: &BlockId<Block>,
|
||||
_method: &str,
|
||||
_call_data: &[u8],
|
||||
_strategy: ExecutionStrategy,
|
||||
_extensions: Option<Extensions>,
|
||||
) -> Result<Vec<u8>, ClientError> {
|
||||
Ok(vec![42])
|
||||
}
|
||||
|
||||
fn contextual_call<
|
||||
'a,
|
||||
IB: Fn() -> ClientResult<()>,
|
||||
EM: Fn(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
_initialize_block_fn: IB,
|
||||
_at: &BlockId<Block>,
|
||||
_method: &str,
|
||||
_call_data: &[u8],
|
||||
_changes: &RefCell<OverlayedChanges>,
|
||||
_offchain_changes: &RefCell<OffchainOverlayedChanges>,
|
||||
_storage_transaction_cache: Option<&RefCell<
|
||||
StorageTransactionCache<
|
||||
Block,
|
||||
<Self::Backend as sc_client_api::backend::Backend<Block>>::State,
|
||||
>
|
||||
>>,
|
||||
_initialize_block: InitializeBlock<'a, Block>,
|
||||
_execution_manager: ExecutionManager<EM>,
|
||||
_native_call: Option<NC>,
|
||||
_proof_recorder: &Option<ProofRecorder<Block>>,
|
||||
_extensions: Option<Extensions>,
|
||||
) -> ClientResult<NativeOrEncoded<R>> where ExecutionManager<EM>: Clone {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn runtime_version(&self, _id: &BlockId<Block>) -> Result<RuntimeVersion, ClientError> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<HashFor<Block>>>(
|
||||
&self,
|
||||
_trie_state: &sp_state_machine::TrieBackend<S, HashFor<Block>>,
|
||||
_overlay: &mut OverlayedChanges,
|
||||
_method: &str,
|
||||
_call_data: &[u8]
|
||||
) -> Result<(Vec<u8>, StorageProof), ClientError> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn native_runtime_version(&self) -> Option<&NativeVersion> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn local_executor() -> NativeExecutor<substrate_test_runtime_client::LocalExecutor> {
|
||||
NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn execution_proof_is_generated_and_checked() {
|
||||
fn execute(remote_client: &TestClient, at: u64, method: &'static str) -> (Vec<u8>, Vec<u8>) {
|
||||
let remote_block_id = BlockId::Number(at);
|
||||
let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap();
|
||||
|
||||
// 'fetch' execution proof from remote node
|
||||
let (remote_result, remote_execution_proof) = remote_client.execution_proof(
|
||||
&remote_block_id,
|
||||
method,
|
||||
&[]
|
||||
).unwrap();
|
||||
|
||||
// check remote execution proof locally
|
||||
let local_result = check_execution_proof::<_, _, BlakeTwo256>(
|
||||
&local_executor(),
|
||||
tasks_executor(),
|
||||
&RemoteCallRequest {
|
||||
block: substrate_test_runtime_client::runtime::Hash::default(),
|
||||
header: remote_header,
|
||||
method: method.into(),
|
||||
call_data: vec![],
|
||||
retry_count: None,
|
||||
},
|
||||
remote_execution_proof,
|
||||
).unwrap();
|
||||
|
||||
(remote_result, local_result)
|
||||
}
|
||||
|
||||
fn execute_with_proof_failure(remote_client: &TestClient, at: u64, method: &'static str) {
|
||||
let remote_block_id = BlockId::Number(at);
|
||||
let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap();
|
||||
|
||||
// 'fetch' execution proof from remote node
|
||||
let (_, remote_execution_proof) = remote_client.execution_proof(
|
||||
&remote_block_id,
|
||||
method,
|
||||
&[]
|
||||
).unwrap();
|
||||
|
||||
// check remote execution proof locally
|
||||
let execution_result = check_execution_proof_with_make_header::<_, _, BlakeTwo256, _>(
|
||||
&local_executor(),
|
||||
tasks_executor(),
|
||||
&RemoteCallRequest {
|
||||
block: substrate_test_runtime_client::runtime::Hash::default(),
|
||||
header: remote_header,
|
||||
method: method.into(),
|
||||
call_data: vec![],
|
||||
retry_count: None,
|
||||
},
|
||||
remote_execution_proof,
|
||||
|header| <Header as HeaderT>::new(
|
||||
at + 1,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
header.hash(),
|
||||
header.digest().clone(), // this makes next header wrong
|
||||
),
|
||||
);
|
||||
match execution_result {
|
||||
Err(sp_blockchain::Error::Execution(_)) => (),
|
||||
_ => panic!("Unexpected execution result: {:?}", execution_result),
|
||||
}
|
||||
}
|
||||
|
||||
// prepare remote client
|
||||
let mut remote_client = substrate_test_runtime_client::new();
|
||||
for i in 1u32..3u32 {
|
||||
let mut digest = Digest::default();
|
||||
digest.push(sp_runtime::generic::DigestItem::Other::<H256>(i.to_le_bytes().to_vec()));
|
||||
remote_client.import_justified(
|
||||
BlockOrigin::Own,
|
||||
remote_client.new_block(digest).unwrap().build().unwrap().block,
|
||||
Default::default(),
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
// check method that doesn't requires environment
|
||||
let (remote, local) = execute(&remote_client, 0, "Core_version");
|
||||
assert_eq!(remote, local);
|
||||
|
||||
let (remote, local) = execute(&remote_client, 2, "Core_version");
|
||||
assert_eq!(remote, local);
|
||||
|
||||
// check method that requires environment
|
||||
let (_, block) = execute(&remote_client, 0, "BlockBuilder_finalize_block");
|
||||
let local_block: Header = Decode::decode(&mut &block[..]).unwrap();
|
||||
assert_eq!(local_block.number, 1);
|
||||
|
||||
let (_, block) = execute(&remote_client, 2, "BlockBuilder_finalize_block");
|
||||
let local_block: Header = Decode::decode(&mut &block[..]).unwrap();
|
||||
assert_eq!(local_block.number, 3);
|
||||
|
||||
// check that proof check doesn't panic even if proof is incorrect AND no panic handler is set
|
||||
execute_with_proof_failure(&remote_client, 2, "Core_version");
|
||||
|
||||
// check that proof check doesn't panic even if proof is incorrect AND panic handler is set
|
||||
sp_panic_handler::set("TEST", "1.2.3");
|
||||
execute_with_proof_failure(&remote_client, 2, "Core_version");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn code_is_executed_at_genesis_only() {
|
||||
let backend = Arc::new(InMemBackend::<Block>::new());
|
||||
let def = H256::default();
|
||||
let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default());
|
||||
let hash0 = header0.hash();
|
||||
let header1 = substrate_test_runtime_client::runtime::Header::new(1, def, def, hash0, Default::default());
|
||||
let hash1 = header1.hash();
|
||||
backend.blockchain().insert(hash0, header0, None, None, NewBlockState::Final).unwrap();
|
||||
backend.blockchain().insert(hash1, header1, None, None, NewBlockState::Final).unwrap();
|
||||
|
||||
let genesis_executor = GenesisCallExecutor::new(backend, DummyCallExecutor);
|
||||
assert_eq!(
|
||||
genesis_executor.call(
|
||||
&BlockId::Number(0),
|
||||
"test_method",
|
||||
&[],
|
||||
ExecutionStrategy::NativeElseWasm,
|
||||
None,
|
||||
).unwrap(),
|
||||
vec![42],
|
||||
);
|
||||
|
||||
let call_on_unavailable = genesis_executor.call(
|
||||
&BlockId::Number(1),
|
||||
"test_method",
|
||||
&[],
|
||||
ExecutionStrategy::NativeElseWasm,
|
||||
None,
|
||||
);
|
||||
|
||||
match call_on_unavailable {
|
||||
Err(ClientError::NotAvailableOnLightClient) => (),
|
||||
_ => unreachable!("unexpected result: {:?}", call_on_unavailable),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Light client data fetcher. Fetches requested data from remote full nodes.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_core::{convert_hash, traits::CodeExecutor};
|
||||
use sp_core::storage::{ChildInfo, ChildType};
|
||||
use sp_runtime::traits::{
|
||||
Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor,
|
||||
AtLeast32Bit, CheckedConversion,
|
||||
};
|
||||
use sp_state_machine::{
|
||||
ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange,
|
||||
InMemoryChangesTrieStorage, TrieBackend, read_proof_check, key_changes_proof_check_with_db,
|
||||
read_child_proof_check, CloneableSpawn,
|
||||
};
|
||||
pub use sp_state_machine::StorageProof;
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
|
||||
pub use sc_client_api::{
|
||||
light::{
|
||||
RemoteCallRequest, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest,
|
||||
RemoteChangesRequest, ChangesProof, RemoteBodyRequest, Fetcher, FetchChecker,
|
||||
Storage as BlockchainStorage,
|
||||
},
|
||||
cht,
|
||||
};
|
||||
use super::blockchain::{Blockchain};
|
||||
use super::call_executor::check_execution_proof;
|
||||
|
||||
/// Remote data checker.
|
||||
pub struct LightDataChecker<E, H, B: BlockT, S: BlockchainStorage<B>> {
|
||||
blockchain: Arc<Blockchain<S>>,
|
||||
executor: E,
|
||||
spawn_handle: Box<dyn CloneableSpawn>,
|
||||
_hasher: PhantomData<(B, H)>,
|
||||
}
|
||||
|
||||
impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
|
||||
/// Create new light data checker.
|
||||
pub fn new(blockchain: Arc<Blockchain<S>>, executor: E, spawn_handle: Box<dyn CloneableSpawn>) -> Self {
|
||||
Self {
|
||||
blockchain, executor, spawn_handle, _hasher: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
/// Check remote changes query proof assuming that CHT-s are of given size.
|
||||
pub fn check_changes_proof_with_cht_size(
|
||||
&self,
|
||||
request: &RemoteChangesRequest<B::Header>,
|
||||
remote_proof: ChangesProof<B::Header>,
|
||||
cht_size: NumberFor<B>,
|
||||
) -> ClientResult<Vec<(NumberFor<B>, u32)>>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Ord + codec::Codec,
|
||||
{
|
||||
// since we need roots of all changes tries for the range begin..max
|
||||
// => remote node can't use max block greater that one that we have passed
|
||||
if remote_proof.max_block > request.max_block.0 || remote_proof.max_block < request.last_block.0 {
|
||||
return Err(ClientError::ChangesTrieAccessFailed(format!(
|
||||
"Invalid max_block used by the remote node: {}. Local: {}..{}..{}",
|
||||
remote_proof.max_block, request.first_block.0, request.last_block.0, request.max_block.0,
|
||||
)).into());
|
||||
}
|
||||
|
||||
// check if remote node has responded with extra changes trie roots proofs
|
||||
// all changes tries roots must be in range [request.first_block.0; request.tries_roots.0)
|
||||
let is_extra_first_root = remote_proof.roots.keys().next()
|
||||
.map(|first_root| *first_root < request.first_block.0
|
||||
|| *first_root >= request.tries_roots.0)
|
||||
.unwrap_or(false);
|
||||
let is_extra_last_root = remote_proof.roots.keys().next_back()
|
||||
.map(|last_root| *last_root >= request.tries_roots.0)
|
||||
.unwrap_or(false);
|
||||
if is_extra_first_root || is_extra_last_root {
|
||||
return Err(ClientError::ChangesTrieAccessFailed(format!(
|
||||
"Extra changes tries roots proofs provided by the remote node: [{:?}..{:?}]. Expected in range: [{}; {})",
|
||||
remote_proof.roots.keys().next(), remote_proof.roots.keys().next_back(),
|
||||
request.first_block.0, request.tries_roots.0,
|
||||
)).into());
|
||||
}
|
||||
|
||||
// if request has been composed when some required headers were already pruned
|
||||
// => remote node has sent us CHT-based proof of required changes tries roots
|
||||
// => check that this proof is correct before proceeding with changes proof
|
||||
let remote_max_block = remote_proof.max_block;
|
||||
let remote_roots = remote_proof.roots;
|
||||
let remote_roots_proof = remote_proof.roots_proof;
|
||||
let remote_proof = remote_proof.proof;
|
||||
if !remote_roots.is_empty() {
|
||||
self.check_changes_tries_proof(
|
||||
cht_size,
|
||||
&remote_roots,
|
||||
remote_roots_proof,
|
||||
)?;
|
||||
}
|
||||
|
||||
// and now check the key changes proof + get the changes
|
||||
let mut result = Vec::new();
|
||||
let proof_storage = InMemoryChangesTrieStorage::with_proof(remote_proof);
|
||||
for config_range in &request.changes_trie_configs {
|
||||
let result_range = key_changes_proof_check_with_db::<H, _>(
|
||||
ChangesTrieConfigurationRange {
|
||||
config: config_range.config.as_ref().ok_or(ClientError::ChangesTriesNotSupported)?,
|
||||
zero: config_range.zero.0,
|
||||
end: config_range.end.map(|(n, _)| n),
|
||||
},
|
||||
&RootsStorage {
|
||||
roots: (request.tries_roots.0, &request.tries_roots.2),
|
||||
prev_roots: &remote_roots,
|
||||
},
|
||||
&proof_storage,
|
||||
request.first_block.0,
|
||||
&ChangesTrieAnchorBlockId {
|
||||
hash: convert_hash(&request.last_block.1),
|
||||
number: request.last_block.0,
|
||||
},
|
||||
remote_max_block,
|
||||
request.storage_key.as_ref(),
|
||||
&request.key)
|
||||
.map_err(|err| ClientError::ChangesTrieAccessFailed(err))?;
|
||||
result.extend(result_range);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Check CHT-based proof for changes tries roots.
|
||||
pub fn check_changes_tries_proof(
|
||||
&self,
|
||||
cht_size: NumberFor<B>,
|
||||
remote_roots: &BTreeMap<NumberFor<B>, B::Hash>,
|
||||
remote_roots_proof: StorageProof,
|
||||
) -> ClientResult<()>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Ord + codec::Codec,
|
||||
{
|
||||
// all the checks are sharing the same storage
|
||||
let storage = remote_roots_proof.into_memory_db();
|
||||
|
||||
// remote_roots.keys() are sorted => we can use this to group changes tries roots
|
||||
// that are belongs to the same CHT
|
||||
let blocks = remote_roots.keys().cloned();
|
||||
cht::for_each_cht_group::<B::Header, _, _, _>(cht_size, blocks, |mut storage, _, cht_blocks| {
|
||||
// get local changes trie CHT root for given CHT
|
||||
// it should be there, because it is never pruned AND request has been composed
|
||||
// when required header has been pruned (=> replaced with CHT)
|
||||
let first_block = cht_blocks.first().cloned()
|
||||
.expect("for_each_cht_group never calls callback with empty groups");
|
||||
let local_cht_root = self.blockchain.storage().changes_trie_cht_root(cht_size, first_block)?
|
||||
.ok_or(ClientError::InvalidCHTProof)?;
|
||||
|
||||
// check changes trie root for every block within CHT range
|
||||
for block in cht_blocks {
|
||||
// check if the proofs storage contains the root
|
||||
// normally this happens in when the proving backend is created, but since
|
||||
// we share the storage for multiple checks, do it here
|
||||
let mut cht_root = H::Out::default();
|
||||
cht_root.as_mut().copy_from_slice(local_cht_root.as_ref());
|
||||
if !storage.contains(&cht_root, EMPTY_PREFIX) {
|
||||
return Err(ClientError::InvalidCHTProof.into());
|
||||
}
|
||||
|
||||
// check proof for single changes trie root
|
||||
let proving_backend = TrieBackend::new(storage, cht_root);
|
||||
let remote_changes_trie_root = remote_roots[&block];
|
||||
cht::check_proof_on_proving_backend::<B::Header, H>(
|
||||
local_cht_root,
|
||||
block,
|
||||
remote_changes_trie_root,
|
||||
&proving_backend,
|
||||
)?;
|
||||
|
||||
// and return the storage to use in following checks
|
||||
storage = proving_backend.into_storage();
|
||||
}
|
||||
|
||||
Ok(storage)
|
||||
}, storage)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
|
||||
where
|
||||
Block: BlockT,
|
||||
E: CodeExecutor + Clone + 'static,
|
||||
H: Hasher,
|
||||
H::Out: Ord + codec::Codec + 'static,
|
||||
S: BlockchainStorage<Block>,
|
||||
{
|
||||
fn check_header_proof(
|
||||
&self,
|
||||
request: &RemoteHeaderRequest<Block::Header>,
|
||||
remote_header: Option<Block::Header>,
|
||||
remote_proof: StorageProof,
|
||||
) -> ClientResult<Block::Header> {
|
||||
let remote_header = remote_header.ok_or_else(||
|
||||
ClientError::from(ClientError::InvalidCHTProof))?;
|
||||
let remote_header_hash = remote_header.hash();
|
||||
cht::check_proof::<Block::Header, H>(
|
||||
request.cht_root,
|
||||
request.block,
|
||||
remote_header_hash,
|
||||
remote_proof,
|
||||
).map(|_| remote_header)
|
||||
}
|
||||
|
||||
fn check_read_proof(
|
||||
&self,
|
||||
request: &RemoteReadRequest<Block::Header>,
|
||||
remote_proof: StorageProof,
|
||||
) -> ClientResult<HashMap<Vec<u8>, Option<Vec<u8>>>> {
|
||||
read_proof_check::<H, _>(
|
||||
convert_hash(request.header.state_root()),
|
||||
remote_proof,
|
||||
request.keys.iter(),
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn check_read_child_proof(
|
||||
&self,
|
||||
request: &RemoteReadChildRequest<Block::Header>,
|
||||
remote_proof: StorageProof,
|
||||
) -> ClientResult<HashMap<Vec<u8>, Option<Vec<u8>>>> {
|
||||
let child_info = match ChildType::from_prefixed_key(&request.storage_key) {
|
||||
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
|
||||
None => return Err("Invalid child type".into()),
|
||||
};
|
||||
read_child_proof_check::<H, _>(
|
||||
convert_hash(request.header.state_root()),
|
||||
remote_proof,
|
||||
&child_info,
|
||||
request.keys.iter(),
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn check_execution_proof(
|
||||
&self,
|
||||
request: &RemoteCallRequest<Block::Header>,
|
||||
remote_proof: StorageProof,
|
||||
) -> ClientResult<Vec<u8>> {
|
||||
check_execution_proof::<_, _, H>(
|
||||
&self.executor,
|
||||
self.spawn_handle.clone(),
|
||||
request,
|
||||
remote_proof,
|
||||
)
|
||||
}
|
||||
|
||||
fn check_changes_proof(
|
||||
&self,
|
||||
request: &RemoteChangesRequest<Block::Header>,
|
||||
remote_proof: ChangesProof<Block::Header>
|
||||
) -> ClientResult<Vec<(NumberFor<Block>, u32)>> {
|
||||
self.check_changes_proof_with_cht_size(request, remote_proof, cht::size())
|
||||
}
|
||||
|
||||
fn check_body_proof(
|
||||
&self,
|
||||
request: &RemoteBodyRequest<Block::Header>,
|
||||
body: Vec<Block::Extrinsic>
|
||||
) -> ClientResult<Vec<Block::Extrinsic>> {
|
||||
// TODO: #2621
|
||||
let extrinsics_root = HashFor::<Block>::ordered_trie_root(
|
||||
body.iter().map(Encode::encode).collect(),
|
||||
);
|
||||
if *request.header.extrinsics_root() == extrinsics_root {
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(format!("RemoteBodyRequest: invalid extrinsics root expected: {} but got {}",
|
||||
*request.header.extrinsics_root(),
|
||||
extrinsics_root,
|
||||
).into())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// A view of BTreeMap<Number, Hash> as a changes trie roots storage.
|
||||
struct RootsStorage<'a, Number: AtLeast32Bit, Hash: 'a> {
|
||||
roots: (Number, &'a [Hash]),
|
||||
prev_roots: &'a BTreeMap<Number, Hash>,
|
||||
}
|
||||
|
||||
impl<'a, H, Number, Hash> ChangesTrieRootsStorage<H, Number> for RootsStorage<'a, Number, Hash>
|
||||
where
|
||||
H: Hasher,
|
||||
Number: std::fmt::Display + std::hash::Hash + Clone + AtLeast32Bit + Encode + Decode + Send + Sync + 'static,
|
||||
Hash: 'a + Send + Sync + Clone + AsRef<[u8]>,
|
||||
{
|
||||
fn build_anchor(
|
||||
&self,
|
||||
_hash: H::Out,
|
||||
) -> Result<sp_state_machine::ChangesTrieAnchorBlockId<H::Out, Number>, String> {
|
||||
Err("build_anchor is only called when building block".into())
|
||||
}
|
||||
|
||||
fn root(
|
||||
&self,
|
||||
_anchor: &ChangesTrieAnchorBlockId<H::Out, Number>,
|
||||
block: Number,
|
||||
) -> Result<Option<H::Out>, String> {
|
||||
// we can't ask for roots from parallel forks here => ignore anchor
|
||||
let root = if block < self.roots.0 {
|
||||
self.prev_roots.get(&Number::unique_saturated_from(block)).cloned()
|
||||
} else {
|
||||
let index: Option<usize> = block.checked_sub(&self.roots.0).and_then(|index| index.checked_into());
|
||||
match index {
|
||||
Some(index) => self.roots.1.get(index as usize).cloned(),
|
||||
None => None,
|
||||
}
|
||||
};
|
||||
|
||||
Ok(root.map(|root| {
|
||||
let mut hasher_root: H::Out = Default::default();
|
||||
hasher_root.as_mut().copy_from_slice(root.as_ref());
|
||||
hasher_root
|
||||
}))
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -30,15 +30,15 @@ use sp_runtime::traits::{Block as BlockT, HashFor};
|
||||
use sp_blockchain::Result as ClientResult;
|
||||
use prometheus_endpoint::Registry;
|
||||
|
||||
use crate::call_executor::LocalCallExecutor;
|
||||
use crate::client::{Client,ClientConfig};
|
||||
use super::call_executor::LocalCallExecutor;
|
||||
use super::client::{Client,ClientConfig};
|
||||
use sc_client_api::{
|
||||
light::Storage as BlockchainStorage, CloneableSpawn,
|
||||
};
|
||||
use crate::light::backend::Backend;
|
||||
use crate::light::blockchain::Blockchain;
|
||||
use crate::light::call_executor::GenesisCallExecutor;
|
||||
use crate::light::fetcher::LightDataChecker;
|
||||
use self::backend::Backend;
|
||||
use self::blockchain::Blockchain;
|
||||
use self::call_executor::GenesisCallExecutor;
|
||||
use self::fetcher::LightDataChecker;
|
||||
|
||||
/// Create an instance of light client blockchain backend.
|
||||
pub fn new_light_blockchain<B: BlockT, S: BlockchainStorage<B>>(storage: S) -> Arc<Blockchain<S>> {
|
||||
@@ -41,70 +41,14 @@
|
||||
//! Additionally, the fourth generic parameter of the `Client` is a marker type representing
|
||||
//! the ways in which the runtime can interface with the outside. Any code that builds a `Client`
|
||||
//! is responsible for putting the right marker.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```
|
||||
//! use std::sync::Arc;
|
||||
//! use sc_client::{Client, in_mem::Backend, LocalCallExecutor};
|
||||
//! use sp_runtime::Storage;
|
||||
//! use sc_executor::{NativeExecutor, WasmExecutionMethod};
|
||||
//!
|
||||
//! // In this example, we're using the `Block` and `RuntimeApi` types from the
|
||||
//! // `substrate-test-runtime-client` crate. These types are automatically generated when
|
||||
//! // compiling a runtime. In a typical use-case, these types would have been to be generated
|
||||
//! // from your runtime.
|
||||
//! use substrate_test_runtime_client::{LocalExecutor, runtime::Block, runtime::RuntimeApi};
|
||||
//!
|
||||
//! let backend = Arc::new(Backend::<Block>::new());
|
||||
//! let client = Client::<_, _, _, RuntimeApi>::new(
|
||||
//! backend.clone(),
|
||||
//! LocalCallExecutor::new(
|
||||
//! backend.clone(),
|
||||
//! NativeExecutor::<LocalExecutor>::new(WasmExecutionMethod::Interpreted, None, 8),
|
||||
//! sp_core::tasks::executor(),
|
||||
//! Default::default(),
|
||||
//! ),
|
||||
//! // This parameter provides the storage for the chain genesis.
|
||||
//! &<Storage>::default(),
|
||||
//! Default::default(),
|
||||
//! Default::default(),
|
||||
//! Default::default(),
|
||||
//! None,
|
||||
//! Default::default(),
|
||||
//! );
|
||||
//! ```
|
||||
//!
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![recursion_limit="128"]
|
||||
|
||||
pub mod cht;
|
||||
pub mod in_mem;
|
||||
pub mod genesis;
|
||||
pub mod light;
|
||||
pub mod leaves;
|
||||
mod call_executor;
|
||||
mod client;
|
||||
mod block_rules;
|
||||
|
||||
pub use sc_client_api::{
|
||||
blockchain,
|
||||
blockchain::well_known_cache_keys,
|
||||
blockchain::Info as ChainInfo,
|
||||
notifications::{StorageEventStream, StorageChangeSet},
|
||||
call_executor::CallExecutor,
|
||||
utils,
|
||||
};
|
||||
pub use crate::{
|
||||
pub use self::{
|
||||
call_executor::LocalCallExecutor,
|
||||
client::{
|
||||
new_with_backend,
|
||||
new_in_mem,
|
||||
ImportNotifications, FinalityNotifications, BlockchainEvents, LockImportRun,
|
||||
BlockImportNotification, Client, ClientConfig, ClientInfo, ExecutionStrategies, FinalityNotification,
|
||||
LongestChain, BlockOf, ProvideUncles, BadBlocks, ForkBlocks, apply_aux,
|
||||
},
|
||||
leaves::LeafSet,
|
||||
client::{new_with_backend, new_in_mem, Client, ClientConfig},
|
||||
};
|
||||
pub use sp_state_machine::{ExecutionStrategy, StorageProof, StateMachine};
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
//! Service configuration.
|
||||
|
||||
pub use sc_client::ExecutionStrategies;
|
||||
pub use sc_client_db::{Database, PruningMode, DatabaseSettingsSrc as DatabaseConfig};
|
||||
pub use sc_network::Multiaddr;
|
||||
pub use sc_network::config::{ExtTransport, MultiaddrWithPeerId, NetworkConfiguration, Role, NodeKeyConfig};
|
||||
pub use sc_executor::WasmExecutionMethod;
|
||||
use sc_client_api::execution_extensions::ExecutionStrategies;
|
||||
|
||||
use std::{future::Future, path::{PathBuf, Path}, pin::Pin, net::SocketAddr, sync::Arc};
|
||||
pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//! Manages communication between them.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![recursion_limit="128"]
|
||||
|
||||
pub mod config;
|
||||
#[macro_use]
|
||||
@@ -26,6 +27,10 @@ pub mod error;
|
||||
|
||||
mod metrics;
|
||||
mod builder;
|
||||
#[cfg(feature = "test-helpers")]
|
||||
pub mod client;
|
||||
#[cfg(not(feature = "test-helpers"))]
|
||||
mod client;
|
||||
mod status_sinks;
|
||||
mod task_manager;
|
||||
|
||||
@@ -38,7 +43,7 @@ use wasm_timer::Instant;
|
||||
use std::task::{Poll, Context};
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use sc_client::Client;
|
||||
use client::Client;
|
||||
use futures::{
|
||||
Future, FutureExt, Stream, StreamExt,
|
||||
compat::*,
|
||||
@@ -49,13 +54,13 @@ use sc_network::{NetworkService, network_state::NetworkState, PeerId, ReportHand
|
||||
use log::{log, warn, debug, error, Level};
|
||||
use codec::{Encode, Decode};
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_runtime::traits::{NumberFor, Block as BlockT};
|
||||
use sp_runtime::traits::{NumberFor, Block as BlockT, BlockIdTo};
|
||||
use parity_util_mem::MallocSizeOf;
|
||||
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
|
||||
|
||||
pub use self::error::Error;
|
||||
pub use self::builder::{
|
||||
new_full_client,
|
||||
new_full_client, new_client,
|
||||
ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend,
|
||||
TFullCallExecutor, TLightCallExecutor,
|
||||
};
|
||||
@@ -66,7 +71,6 @@ pub use sc_chain_spec::{
|
||||
};
|
||||
pub use sp_transaction_pool::{TransactionPool, InPoolTransaction, error::IntoPoolError};
|
||||
pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions;
|
||||
pub use sc_client::FinalityNotifications;
|
||||
pub use sc_rpc::Metadata as RpcMetadata;
|
||||
pub use sc_executor::NativeExecutionDispatch;
|
||||
#[doc(hidden)]
|
||||
@@ -76,6 +80,17 @@ pub use sc_network::config::{FinalityProofProvider, OnDemand, BoxFinalityProofRe
|
||||
pub use sc_tracing::TracingReceiver;
|
||||
pub use task_manager::SpawnTaskHandle;
|
||||
use task_manager::TaskManager;
|
||||
use sp_blockchain::{HeaderBackend, HeaderMetadata, ProvideCache};
|
||||
use sp_api::{ProvideRuntimeApi, CallApiAt, ApiExt, ConstructRuntimeApi, ApiErrorExt};
|
||||
use sc_client_api::{
|
||||
LockImportRun, Backend as BackendT, ProofProvider, ProvideUncles,
|
||||
StorageProvider, ExecutorProvider, Finalizer, AuxStore, Backend,
|
||||
BlockBackend, BlockchainEvents, CallExecutor, TransactionFor,
|
||||
UsageProvider,
|
||||
};
|
||||
use sc_block_builder::BlockBuilderProvider;
|
||||
use sp_consensus::{block_validation::Chain, BlockImport};
|
||||
use sp_block_builder::BlockBuilder;
|
||||
|
||||
const DEFAULT_PROTOCOL_ID: &str = "sup";
|
||||
|
||||
@@ -116,21 +131,104 @@ pub struct Service<TBl, TCl, TSc, TNetStatus, TNet, TTxPool, TOc> {
|
||||
|
||||
impl<TBl, TCl, TSc, TNetStatus, TNet, TTxPool, TOc> Unpin for Service<TBl, TCl, TSc, TNetStatus, TNet, TTxPool, TOc> {}
|
||||
|
||||
/// Client super trait, use this instead of the concrete Client type.
|
||||
pub trait ClientProvider<
|
||||
Block: BlockT,
|
||||
Backend: BackendT<Block>,
|
||||
Executor: CallExecutor<Block>,
|
||||
Runtime: ConstructRuntimeApi<Block, Self>,
|
||||
>:
|
||||
HeaderBackend<Block>
|
||||
+ ProvideRuntimeApi<
|
||||
Block,
|
||||
Api = <Runtime as ConstructRuntimeApi<Block, Self>>::RuntimeApi
|
||||
>
|
||||
+ LockImportRun<Block, Backend>
|
||||
+ ProofProvider<Block>
|
||||
+ BlockBuilderProvider<Backend, Block, Self>
|
||||
+ ProvideUncles<Block>
|
||||
+ StorageProvider<Block, Backend>
|
||||
+ Chain<Block>
|
||||
+ HeaderMetadata<Block, Error = sp_blockchain::Error>
|
||||
+ ExecutorProvider<Block, Executor = Executor>
|
||||
+ ProvideCache<Block>
|
||||
+ BlockIdTo<Block, Error = sp_blockchain::Error>
|
||||
+ CallApiAt<
|
||||
Block,
|
||||
Error = sp_blockchain::Error,
|
||||
StateBackend = <Backend as BackendT<Block>>::State
|
||||
>
|
||||
+ BlockImport<
|
||||
Block,
|
||||
Error = sp_consensus::Error,
|
||||
Transaction = TransactionFor<Backend, Block>
|
||||
>
|
||||
+ Finalizer<Block, Backend>
|
||||
+ BlockchainEvents<Block>
|
||||
+ BlockBackend<Block>
|
||||
+ UsageProvider<Block>
|
||||
+ AuxStore
|
||||
{}
|
||||
|
||||
impl<Block, Backend, Executor, Runtime> ClientProvider<Block, Backend, Executor, Runtime>
|
||||
for
|
||||
Client<Backend, Executor, Block, Runtime>
|
||||
where
|
||||
Block: BlockT,
|
||||
Backend: BackendT<Block>,
|
||||
Executor: CallExecutor<Block>,
|
||||
Runtime: ConstructRuntimeApi<Block, Self>,
|
||||
Self: HeaderBackend<Block>
|
||||
+ ProvideRuntimeApi<
|
||||
Block,
|
||||
Api = <Runtime as ConstructRuntimeApi<Block, Self>>::RuntimeApi
|
||||
>
|
||||
+ LockImportRun<Block, Backend>
|
||||
+ ProofProvider<Block>
|
||||
+ BlockBuilderProvider<Backend, Block, Self>
|
||||
+ ProvideUncles<Block>
|
||||
+ StorageProvider<Block, Backend>
|
||||
+ Chain<Block>
|
||||
+ HeaderMetadata<Block, Error = sp_blockchain::Error>
|
||||
+ ExecutorProvider<Block, Executor = Executor>
|
||||
+ ProvideCache<Block>
|
||||
+ BlockIdTo<Block, Error = sp_blockchain::Error>
|
||||
+ CallApiAt<
|
||||
Block,
|
||||
Error = sp_blockchain::Error,
|
||||
StateBackend = <Backend as BackendT<Block>>::State
|
||||
>
|
||||
+ BlockImport<
|
||||
Block,
|
||||
Error = sp_consensus::Error,
|
||||
Transaction = TransactionFor<Backend, Block>
|
||||
>
|
||||
+ Finalizer<Block, Backend>
|
||||
+ BlockchainEvents<Block>
|
||||
+ BlockBackend<Block>
|
||||
+ UsageProvider<Block>
|
||||
+ AuxStore
|
||||
{}
|
||||
|
||||
/// Abstraction over a Substrate service.
|
||||
pub trait AbstractService: 'static + Future<Output = Result<(), Error>> +
|
||||
Spawn + Send + Unpin {
|
||||
pub trait AbstractService: Future<Output = Result<(), Error>> + Send + Unpin + Spawn + 'static {
|
||||
/// Type of block of this chain.
|
||||
type Block: BlockT;
|
||||
/// Backend storage for the client.
|
||||
type Backend: 'static + sc_client_api::backend::Backend<Self::Block>;
|
||||
type Backend: 'static + BackendT<Self::Block>;
|
||||
/// How to execute calls towards the runtime.
|
||||
type CallExecutor: 'static + sc_client::CallExecutor<Self::Block> + Send + Sync + Clone;
|
||||
type CallExecutor: 'static + CallExecutor<Self::Block> + Send + Sync + Clone;
|
||||
/// API that the runtime provides.
|
||||
type RuntimeApi: Send + Sync;
|
||||
/// Chain selection algorithm.
|
||||
type SelectChain: sp_consensus::SelectChain<Self::Block>;
|
||||
/// Transaction pool.
|
||||
type TransactionPool: TransactionPool<Block = Self::Block> + MallocSizeOfWasm;
|
||||
/// The generic Client type, the bounds here are the ones specifically required by
|
||||
/// internal crates like sc_informant.
|
||||
type Client:
|
||||
HeaderMetadata<Self::Block, Error = sp_blockchain::Error> + UsageProvider<Self::Block>
|
||||
+ BlockchainEvents<Self::Block> + HeaderBackend<Self::Block> + Send + Sync;
|
||||
|
||||
/// Get event stream for telemetry connection established events.
|
||||
fn telemetry_on_connect_stream(&self) -> TracingUnboundedReceiver<()>;
|
||||
@@ -170,7 +268,7 @@ pub trait AbstractService: 'static + Future<Output = Result<(), Error>> +
|
||||
fn rpc_query(&self, mem: &RpcSession, request: &str) -> Pin<Box<dyn Future<Output = Option<String>> + Send>>;
|
||||
|
||||
/// Get shared client instance.
|
||||
fn client(&self) -> Arc<sc_client::Client<Self::Backend, Self::CallExecutor, Self::Block, Self::RuntimeApi>>;
|
||||
fn client(&self) -> Arc<Self::Client>;
|
||||
|
||||
/// Get clone of select chain.
|
||||
fn select_chain(&self) -> Option<Self::SelectChain>;
|
||||
@@ -198,9 +296,14 @@ impl<TBl, TBackend, TExec, TRtApi, TSc, TExPool, TOc> AbstractService for
|
||||
NetworkService<TBl, TBl::Hash>, TExPool, TOc>
|
||||
where
|
||||
TBl: BlockT,
|
||||
TBackend: 'static + sc_client_api::backend::Backend<TBl>,
|
||||
TExec: 'static + sc_client::CallExecutor<TBl> + Send + Sync + Clone,
|
||||
TRtApi: 'static + Send + Sync,
|
||||
TBackend: 'static + Backend<TBl>,
|
||||
TExec: 'static + CallExecutor<TBl, Backend = TBackend> + Send + Sync + Clone,
|
||||
TRtApi: 'static + Send + Sync + ConstructRuntimeApi<TBl, Client<TBackend, TExec, TBl, TRtApi>>,
|
||||
<TRtApi as ConstructRuntimeApi<TBl, Client<TBackend, TExec, TBl, TRtApi>>>::RuntimeApi:
|
||||
sp_api::Core<TBl>
|
||||
+ ApiExt<TBl, StateBackend = TBackend::State>
|
||||
+ ApiErrorExt<Error = sp_blockchain::Error>
|
||||
+ BlockBuilder<TBl>,
|
||||
TSc: sp_consensus::SelectChain<TBl> + 'static + Clone + Send + Unpin,
|
||||
TExPool: 'static + TransactionPool<Block = TBl> + MallocSizeOfWasm,
|
||||
TOc: 'static + Send + Sync,
|
||||
@@ -211,6 +314,7 @@ where
|
||||
type RuntimeApi = TRtApi;
|
||||
type SelectChain = TSc;
|
||||
type TransactionPool = TExPool;
|
||||
type Client = Client<Self::Backend, Self::CallExecutor, Self::Block, Self::RuntimeApi>;
|
||||
|
||||
fn telemetry_on_connect_stream(&self) -> TracingUnboundedReceiver<()> {
|
||||
let (sink, stream) = tracing_unbounded("mpsc_telemetry_on_connect");
|
||||
@@ -254,7 +358,7 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
fn client(&self) -> Arc<sc_client::Client<Self::Backend, Self::CallExecutor, Self::Block, Self::RuntimeApi>> {
|
||||
fn client(&self) -> Arc<Self::Client> {
|
||||
self.client.clone()
|
||||
}
|
||||
|
||||
@@ -326,7 +430,7 @@ impl<TBl, TCl, TSc, TNetStatus, TNet, TTxPool, TOc> Spawn for
|
||||
/// The `status_sink` contain a list of senders to send a periodic network status to.
|
||||
fn build_network_future<
|
||||
B: BlockT,
|
||||
C: sc_client::BlockchainEvents<B>,
|
||||
C: BlockchainEvents<B>,
|
||||
H: sc_network::ExHashT
|
||||
> (
|
||||
role: Role,
|
||||
|
||||
@@ -18,11 +18,11 @@ use std::convert::TryFrom;
|
||||
|
||||
use crate::NetworkStatus;
|
||||
use prometheus_endpoint::{register, Gauge, U64, F64, Registry, PrometheusError, Opts, GaugeVec};
|
||||
use sc_client::ClientInfo;
|
||||
use sc_telemetry::{telemetry, SUBSTRATE_INFO};
|
||||
use sp_runtime::traits::{NumberFor, Block, SaturatedConversion, UniqueSaturatedInto};
|
||||
use sp_transaction_pool::PoolStatus;
|
||||
use sp_utils::metrics::register_globals;
|
||||
use sc_client_api::ClientInfo;
|
||||
|
||||
use sysinfo::{self, ProcessExt, SystemExt};
|
||||
|
||||
|
||||
@@ -8,21 +8,36 @@ publish = false
|
||||
homepage = "https://substrate.dev"
|
||||
repository = "https://github.com/paritytech/substrate/"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
hex-literal = "0.2.1"
|
||||
tempfile = "3.1.0"
|
||||
tokio = "0.1.22"
|
||||
futures01 = { package = "futures", version = "0.1.29" }
|
||||
log = "0.4.8"
|
||||
env_logger = "0.7.0"
|
||||
fdlimit = "0.1.4"
|
||||
parking_lot = "0.10.0"
|
||||
sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" }
|
||||
sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" }
|
||||
sp-state-machine = { version = "0.8.0-dev", path = "../../../primitives/state-machine" }
|
||||
sp-externalities = { version = "0.8.0-dev", path = "../../../primitives/externalities" }
|
||||
sp-trie = { version = "2.0.0-dev", path = "../../../primitives/trie" }
|
||||
sp-storage = { version = "2.0.0-dev", path = "../../../primitives/storage" }
|
||||
sc-client-db = { version = "0.8.0-dev", default-features = false, path = "../../db" }
|
||||
futures = { version = "0.3.1", features = ["compat"] }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, path = "../../service" }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, features = ["test-helpers"], path = "../../service" }
|
||||
sc-network = { version = "0.8.0-dev", path = "../../network" }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../" }
|
||||
sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" }
|
||||
sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" }
|
||||
sp-transaction-pool = { version = "2.0.0-dev", path = "../../../primitives/transaction-pool" }
|
||||
substrate-test-runtime = { version = "2.0.0-dev", path = "../../../test-utils/runtime" }
|
||||
substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../api" }
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "../../block-builder" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "../../executor" }
|
||||
sp-panic-handler = { version = "2.0.0-dev", path = "../../../primitives/panic-handler" }
|
||||
parity-scale-codec = "1.3.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use sp_core::offchain::{OffchainStorage, storage::InMemOffchainStorage};
|
||||
use std::sync::Arc;
|
||||
|
||||
type TestBackend = sc_client_api::in_mem::Backend<substrate_test_runtime::Block>;
|
||||
|
||||
#[test]
|
||||
fn test_leaves_with_complex_block_tree() {
|
||||
let backend = Arc::new(TestBackend::new());
|
||||
|
||||
substrate_test_runtime_client::trait_tests::test_leaves_for_backend(backend);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blockchain_query_by_number_gets_canonical() {
|
||||
let backend = Arc::new(TestBackend::new());
|
||||
|
||||
substrate_test_runtime_client::trait_tests::test_blockchain_query_by_number_gets_canonical(backend);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn in_memory_offchain_storage() {
|
||||
|
||||
let mut storage = InMemOffchainStorage::default();
|
||||
assert_eq!(storage.get(b"A", b"B"), None);
|
||||
assert_eq!(storage.get(b"B", b"A"), None);
|
||||
|
||||
storage.set(b"A", b"B", b"C");
|
||||
assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec()));
|
||||
assert_eq!(storage.get(b"B", b"A"), None);
|
||||
|
||||
storage.compare_and_set(b"A", b"B", Some(b"X"), b"D");
|
||||
assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec()));
|
||||
storage.compare_and_set(b"A", b"B", Some(b"C"), b"D");
|
||||
assert_eq!(storage.get(b"A", b"B"), Some(b"D".to_vec()));
|
||||
|
||||
assert!(!storage.compare_and_set(b"B", b"A", Some(b""), b"Y"));
|
||||
assert!(storage.compare_and_set(b"B", b"A", None, b"X"));
|
||||
assert_eq!(storage.get(b"B", b"A"), Some(b"X".to_vec()));
|
||||
}
|
||||
@@ -0,0 +1,896 @@
|
||||
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
use sc_service::client::light::{
|
||||
call_executor::{
|
||||
GenesisCallExecutor,
|
||||
check_execution_proof,
|
||||
check_execution_proof_with_make_header,
|
||||
},
|
||||
fetcher::LightDataChecker,
|
||||
blockchain::{BlockchainCache, Blockchain},
|
||||
backend::{Backend, GenesisOrUnavailableState},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use sp_runtime::{
|
||||
traits::{BlakeTwo256, HashFor, NumberFor},
|
||||
generic::BlockId, traits::{Block as _, Header as HeaderT}, Digest,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use parking_lot::Mutex;
|
||||
use substrate_test_runtime_client::{
|
||||
runtime::{Hash, Block, Header}, TestClient, ClientBlockImportExt,
|
||||
};
|
||||
use sp_api::{InitializeBlock, StorageTransactionCache, ProofRecorder, OffchainOverlayedChanges};
|
||||
use sp_consensus::{BlockOrigin};
|
||||
use sc_executor::{NativeExecutor, WasmExecutionMethod, RuntimeVersion, NativeVersion};
|
||||
use sp_core::{H256, tasks::executor as tasks_executor, NativeOrEncoded};
|
||||
use sc_client_api::{blockchain::Info, backend::NewBlockState, Backend as ClientBackend, ProofProvider, in_mem::{Backend as InMemBackend, Blockchain as InMemoryBlockchain}, AuxStore, Storage, CallExecutor, cht, ExecutionStrategy, StorageProof, BlockImportOperation, RemoteCallRequest, StorageProvider, ChangesProof, RemoteBodyRequest, RemoteReadRequest, RemoteChangesRequest, FetchChecker, RemoteReadChildRequest, RemoteHeaderRequest};
|
||||
use sp_externalities::Extensions;
|
||||
use sc_block_builder::BlockBuilderProvider;
|
||||
use sp_blockchain::{
|
||||
BlockStatus, Result as ClientResult, Error as ClientError, CachedHeaderMetadata,
|
||||
HeaderBackend, well_known_cache_keys
|
||||
};
|
||||
use std::panic::UnwindSafe;
|
||||
use std::cell::RefCell;
|
||||
use sp_state_machine::{OverlayedChanges, ExecutionManager};
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
use super::prepare_client_with_key_changes;
|
||||
use substrate_test_runtime_client::{
|
||||
AccountKeyring, runtime::{self, Extrinsic},
|
||||
};
|
||||
|
||||
use sp_core::{blake2_256, ChangesTrieConfiguration, storage::{well_known_keys, StorageKey, ChildInfo}};
|
||||
use sp_state_machine::Backend as _;
|
||||
|
||||
pub type DummyBlockchain = Blockchain<DummyStorage>;
|
||||
|
||||
pub struct DummyStorage {
|
||||
pub changes_tries_cht_roots: HashMap<u64, Hash>,
|
||||
pub aux_store: Mutex<HashMap<Vec<u8>, Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl DummyStorage {
|
||||
pub fn new() -> Self {
|
||||
DummyStorage {
|
||||
changes_tries_cht_roots: HashMap::new(),
|
||||
aux_store: Mutex::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_blockchain::HeaderBackend<Block> for DummyStorage {
|
||||
fn header(&self, _id: BlockId<Block>) -> ClientResult<Option<Header>> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn info(&self) -> Info<Block> {
|
||||
panic!("Test error")
|
||||
}
|
||||
|
||||
fn status(&self, _id: BlockId<Block>) -> ClientResult<BlockStatus> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn number(&self, hash: Hash) -> ClientResult<Option<NumberFor<Block>>> {
|
||||
if hash == Default::default() {
|
||||
Ok(Some(Default::default()))
|
||||
} else {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self, number: u64) -> ClientResult<Option<Hash>> {
|
||||
if number == 0 {
|
||||
Ok(Some(Default::default()))
|
||||
} else {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_blockchain::HeaderMetadata<Block> for DummyStorage {
|
||||
type Error = ClientError;
|
||||
|
||||
fn header_metadata(&self, hash: Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
|
||||
self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header))
|
||||
.ok_or(ClientError::UnknownBlock("header not found".to_owned()))
|
||||
}
|
||||
fn insert_header_metadata(&self, _hash: Hash, _metadata: CachedHeaderMetadata<Block>) {}
|
||||
fn remove_header_metadata(&self, _hash: Hash) {}
|
||||
}
|
||||
|
||||
impl AuxStore for DummyStorage {
|
||||
fn insert_aux<
|
||||
'a,
|
||||
'b: 'a,
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
>(&self, insert: I, _delete: D) -> ClientResult<()> {
|
||||
for (k, v) in insert.into_iter() {
|
||||
self.aux_store.lock().insert(k.to_vec(), v.to_vec());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_aux(&self, key: &[u8]) -> ClientResult<Option<Vec<u8>>> {
|
||||
Ok(self.aux_store.lock().get(key).cloned())
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage<Block> for DummyStorage {
|
||||
fn import_header(
|
||||
&self,
|
||||
_header: Header,
|
||||
_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
|
||||
_state: NewBlockState,
|
||||
_aux_ops: Vec<(Vec<u8>, Option<Vec<u8>>)>,
|
||||
) -> ClientResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_head(&self, _block: BlockId<Block>) -> ClientResult<()> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn finalize_header(&self, _block: BlockId<Block>) -> ClientResult<()> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn last_finalized(&self) -> ClientResult<Hash> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn header_cht_root(&self, _cht_size: u64, _block: u64) -> ClientResult<Option<Hash>> {
|
||||
Err(ClientError::Backend("Test error".into()))
|
||||
}
|
||||
|
||||
fn changes_trie_cht_root(&self, cht_size: u64, block: u64) -> ClientResult<Option<Hash>> {
|
||||
cht::block_to_cht_number(cht_size, block)
|
||||
.and_then(|cht_num| self.changes_tries_cht_roots.get(&cht_num))
|
||||
.cloned()
|
||||
.ok_or_else(|| ClientError::Backend(
|
||||
format!("Test error: CHT for block #{} not found", block)
|
||||
).into())
|
||||
.map(Some)
|
||||
}
|
||||
|
||||
fn cache(&self) -> Option<Arc<dyn BlockchainCache<Block>>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn usage_info(&self) -> Option<sc_client_api::UsageInfo> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
struct DummyCallExecutor;
|
||||
|
||||
impl CallExecutor<Block> for DummyCallExecutor {
|
||||
type Error = ClientError;
|
||||
|
||||
type Backend = substrate_test_runtime_client::Backend;
|
||||
|
||||
fn call(
|
||||
&self,
|
||||
_id: &BlockId<Block>,
|
||||
_method: &str,
|
||||
_call_data: &[u8],
|
||||
_strategy: ExecutionStrategy,
|
||||
_extensions: Option<Extensions>,
|
||||
) -> Result<Vec<u8>, ClientError> {
|
||||
Ok(vec![42])
|
||||
}
|
||||
|
||||
fn contextual_call<
|
||||
'a,
|
||||
IB: Fn() -> ClientResult<()>,
|
||||
EM: Fn(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> Result<R, String> + UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
_initialize_block_fn: IB,
|
||||
_at: &BlockId<Block>,
|
||||
_method: &str,
|
||||
_call_data: &[u8],
|
||||
_changes: &RefCell<OverlayedChanges>,
|
||||
_offchain_changes: &RefCell<OffchainOverlayedChanges>,
|
||||
_storage_transaction_cache: Option<&RefCell<
|
||||
StorageTransactionCache<
|
||||
Block,
|
||||
<Self::Backend as sc_client_api::backend::Backend<Block>>::State,
|
||||
>
|
||||
>>,
|
||||
_initialize_block: InitializeBlock<'a, Block>,
|
||||
_execution_manager: ExecutionManager<EM>,
|
||||
_native_call: Option<NC>,
|
||||
_proof_recorder: &Option<ProofRecorder<Block>>,
|
||||
_extensions: Option<Extensions>,
|
||||
) -> ClientResult<NativeOrEncoded<R>> where ExecutionManager<EM>: Clone {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn runtime_version(&self, _id: &BlockId<Block>) -> Result<RuntimeVersion, ClientError> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<HashFor<Block>>>(
|
||||
&self,
|
||||
_trie_state: &sp_state_machine::TrieBackend<S, HashFor<Block>>,
|
||||
_overlay: &mut OverlayedChanges,
|
||||
_method: &str,
|
||||
_call_data: &[u8]
|
||||
) -> Result<(Vec<u8>, StorageProof), ClientError> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn native_runtime_version(&self) -> Option<&NativeVersion> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn local_executor() -> NativeExecutor<substrate_test_runtime_client::LocalExecutor> {
|
||||
NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn local_state_is_created_when_genesis_state_is_available() {
|
||||
let def = Default::default();
|
||||
let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default());
|
||||
|
||||
let backend: Backend<_, BlakeTwo256> = Backend::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
);
|
||||
let mut op = backend.begin_operation().unwrap();
|
||||
op.set_block_data(header0, None, None, NewBlockState::Final).unwrap();
|
||||
op.reset_storage(Default::default()).unwrap();
|
||||
backend.commit_operation(op).unwrap();
|
||||
|
||||
match backend.state_at(BlockId::Number(0)).unwrap() {
|
||||
GenesisOrUnavailableState::Genesis(_) => (),
|
||||
_ => panic!("unexpected state"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unavailable_state_is_created_when_genesis_state_is_unavailable() {
|
||||
let backend: Backend<_, BlakeTwo256> = Backend::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
);
|
||||
|
||||
match backend.state_at(BlockId::Number(0)).unwrap() {
|
||||
GenesisOrUnavailableState::Unavailable => (),
|
||||
_ => panic!("unexpected state"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn light_aux_store_is_updated_via_non_importing_op() {
|
||||
let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new())));
|
||||
let mut op = ClientBackend::<Block>::begin_operation(&backend).unwrap();
|
||||
BlockImportOperation::<Block>::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap();
|
||||
ClientBackend::<Block>::commit_operation(&backend, op).unwrap();
|
||||
|
||||
assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn execution_proof_is_generated_and_checked() {
|
||||
fn execute(remote_client: &TestClient, at: u64, method: &'static str) -> (Vec<u8>, Vec<u8>) {
|
||||
let remote_block_id = BlockId::Number(at);
|
||||
let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap();
|
||||
|
||||
// 'fetch' execution proof from remote node
|
||||
let (remote_result, remote_execution_proof) = remote_client.execution_proof(
|
||||
&remote_block_id,
|
||||
method,
|
||||
&[]
|
||||
).unwrap();
|
||||
|
||||
// check remote execution proof locally
|
||||
let local_result = check_execution_proof::<_, _, BlakeTwo256>(
|
||||
&local_executor(),
|
||||
tasks_executor(),
|
||||
&RemoteCallRequest {
|
||||
block: substrate_test_runtime_client::runtime::Hash::default(),
|
||||
header: remote_header,
|
||||
method: method.into(),
|
||||
call_data: vec![],
|
||||
retry_count: None,
|
||||
},
|
||||
remote_execution_proof,
|
||||
).unwrap();
|
||||
|
||||
(remote_result, local_result)
|
||||
}
|
||||
|
||||
fn execute_with_proof_failure(remote_client: &TestClient, at: u64, method: &'static str) {
|
||||
let remote_block_id = BlockId::Number(at);
|
||||
let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap();
|
||||
|
||||
// 'fetch' execution proof from remote node
|
||||
let (_, remote_execution_proof) = remote_client.execution_proof(
|
||||
&remote_block_id,
|
||||
method,
|
||||
&[]
|
||||
).unwrap();
|
||||
|
||||
// check remote execution proof locally
|
||||
let execution_result = check_execution_proof_with_make_header::<_, _, BlakeTwo256, _>(
|
||||
&local_executor(),
|
||||
tasks_executor(),
|
||||
&RemoteCallRequest {
|
||||
block: substrate_test_runtime_client::runtime::Hash::default(),
|
||||
header: remote_header,
|
||||
method: method.into(),
|
||||
call_data: vec![],
|
||||
retry_count: None,
|
||||
},
|
||||
remote_execution_proof,
|
||||
|header| <Header as HeaderT>::new(
|
||||
at + 1,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
header.hash(),
|
||||
header.digest().clone(), // this makes next header wrong
|
||||
),
|
||||
);
|
||||
match execution_result {
|
||||
Err(sp_blockchain::Error::Execution(_)) => (),
|
||||
_ => panic!("Unexpected execution result: {:?}", execution_result),
|
||||
}
|
||||
}
|
||||
|
||||
// prepare remote client
|
||||
let mut remote_client = substrate_test_runtime_client::new();
|
||||
for i in 1u32..3u32 {
|
||||
let mut digest = Digest::default();
|
||||
digest.push(sp_runtime::generic::DigestItem::Other::<H256>(i.to_le_bytes().to_vec()));
|
||||
remote_client.import_justified(
|
||||
BlockOrigin::Own,
|
||||
remote_client.new_block(digest).unwrap().build().unwrap().block,
|
||||
Default::default(),
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
// check method that doesn't requires environment
|
||||
let (remote, local) = execute(&remote_client, 0, "Core_version");
|
||||
assert_eq!(remote, local);
|
||||
|
||||
let (remote, local) = execute(&remote_client, 2, "Core_version");
|
||||
assert_eq!(remote, local);
|
||||
|
||||
// check method that requires environment
|
||||
let (_, block) = execute(&remote_client, 0, "BlockBuilder_finalize_block");
|
||||
let local_block: Header = Decode::decode(&mut &block[..]).unwrap();
|
||||
assert_eq!(local_block.number, 1);
|
||||
|
||||
let (_, block) = execute(&remote_client, 2, "BlockBuilder_finalize_block");
|
||||
let local_block: Header = Decode::decode(&mut &block[..]).unwrap();
|
||||
assert_eq!(local_block.number, 3);
|
||||
|
||||
// check that proof check doesn't panic even if proof is incorrect AND no panic handler is set
|
||||
execute_with_proof_failure(&remote_client, 2, "Core_version");
|
||||
|
||||
// check that proof check doesn't panic even if proof is incorrect AND panic handler is set
|
||||
sp_panic_handler::set("TEST", "1.2.3");
|
||||
execute_with_proof_failure(&remote_client, 2, "Core_version");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn code_is_executed_at_genesis_only() {
|
||||
let backend = Arc::new(InMemBackend::<Block>::new());
|
||||
let def = H256::default();
|
||||
let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default());
|
||||
let hash0 = header0.hash();
|
||||
let header1 = substrate_test_runtime_client::runtime::Header::new(1, def, def, hash0, Default::default());
|
||||
let hash1 = header1.hash();
|
||||
backend.blockchain().insert(hash0, header0, None, None, NewBlockState::Final).unwrap();
|
||||
backend.blockchain().insert(hash1, header1, None, None, NewBlockState::Final).unwrap();
|
||||
|
||||
let genesis_executor = GenesisCallExecutor::new(backend, DummyCallExecutor);
|
||||
assert_eq!(
|
||||
genesis_executor.call(
|
||||
&BlockId::Number(0),
|
||||
"test_method",
|
||||
&[],
|
||||
ExecutionStrategy::NativeElseWasm,
|
||||
None,
|
||||
).unwrap(),
|
||||
vec![42],
|
||||
);
|
||||
|
||||
let call_on_unavailable = genesis_executor.call(
|
||||
&BlockId::Number(1),
|
||||
"test_method",
|
||||
&[],
|
||||
ExecutionStrategy::NativeElseWasm,
|
||||
None,
|
||||
);
|
||||
|
||||
match call_on_unavailable {
|
||||
Err(ClientError::NotAvailableOnLightClient) => (),
|
||||
_ => unreachable!("unexpected result: {:?}", call_on_unavailable),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type TestChecker = LightDataChecker<
|
||||
NativeExecutor<substrate_test_runtime_client::LocalExecutor>,
|
||||
BlakeTwo256,
|
||||
Block,
|
||||
DummyStorage,
|
||||
>;
|
||||
|
||||
fn prepare_for_read_proof_check() -> (TestChecker, Header, StorageProof, u32) {
|
||||
// prepare remote client
|
||||
let remote_client = substrate_test_runtime_client::new();
|
||||
let remote_block_id = BlockId::Number(0);
|
||||
let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap();
|
||||
let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap();
|
||||
remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap()
|
||||
.storage_root(::std::iter::empty()).0.into();
|
||||
|
||||
// 'fetch' read proof from remote node
|
||||
let heap_pages = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::HEAP_PAGES.to_vec()))
|
||||
.unwrap()
|
||||
.and_then(|v| Decode::decode(&mut &v.0[..]).ok()).unwrap();
|
||||
let remote_read_proof = remote_client.read_proof(
|
||||
&remote_block_id,
|
||||
&mut std::iter::once(well_known_keys::HEAP_PAGES),
|
||||
).unwrap();
|
||||
|
||||
// check remote read proof locally
|
||||
let local_storage = InMemoryBlockchain::<Block>::new();
|
||||
local_storage.insert(
|
||||
remote_block_hash,
|
||||
remote_block_header.clone(),
|
||||
None,
|
||||
None,
|
||||
NewBlockState::Final,
|
||||
).unwrap();
|
||||
let local_checker = LightDataChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
(local_checker, remote_block_header, remote_read_proof, heap_pages)
|
||||
}
|
||||
|
||||
fn prepare_for_read_child_proof_check() -> (TestChecker, Header, StorageProof, Vec<u8>) {
|
||||
use substrate_test_runtime_client::DefaultTestClientBuilderExt;
|
||||
use substrate_test_runtime_client::TestClientBuilderExt;
|
||||
let child_info = ChildInfo::new_default(b"child1");
|
||||
let child_info = &child_info;
|
||||
// prepare remote client
|
||||
let remote_client = substrate_test_runtime_client::TestClientBuilder::new()
|
||||
.add_extra_child_storage(
|
||||
child_info,
|
||||
b"key1".to_vec(),
|
||||
b"value1".to_vec(),
|
||||
).build();
|
||||
let remote_block_id = BlockId::Number(0);
|
||||
let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap();
|
||||
let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap();
|
||||
remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap()
|
||||
.storage_root(::std::iter::empty()).0.into();
|
||||
|
||||
// 'fetch' child read proof from remote node
|
||||
let child_value = remote_client.child_storage(
|
||||
&remote_block_id,
|
||||
child_info,
|
||||
&StorageKey(b"key1".to_vec()),
|
||||
).unwrap().unwrap().0;
|
||||
assert_eq!(b"value1"[..], child_value[..]);
|
||||
let remote_read_proof = remote_client.read_child_proof(
|
||||
&remote_block_id,
|
||||
child_info,
|
||||
&mut std::iter::once("key1".as_bytes()),
|
||||
).unwrap();
|
||||
|
||||
// check locally
|
||||
let local_storage = InMemoryBlockchain::<Block>::new();
|
||||
local_storage.insert(
|
||||
remote_block_hash,
|
||||
remote_block_header.clone(),
|
||||
None,
|
||||
None,
|
||||
NewBlockState::Final,
|
||||
).unwrap();
|
||||
let local_checker = LightDataChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
(local_checker, remote_block_header, remote_read_proof, child_value)
|
||||
}
|
||||
|
||||
fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, StorageProof) {
|
||||
// prepare remote client
|
||||
let mut remote_client = substrate_test_runtime_client::new();
|
||||
let mut local_headers_hashes = Vec::new();
|
||||
for i in 0..4 {
|
||||
let block = remote_client.new_block(Default::default()).unwrap().build().unwrap().block;
|
||||
remote_client.import(BlockOrigin::Own, block).unwrap();
|
||||
local_headers_hashes.push(
|
||||
remote_client.block_hash(i + 1)
|
||||
.map_err(|_| ClientError::Backend("TestError".into()))
|
||||
);
|
||||
}
|
||||
|
||||
// 'fetch' header proof from remote node
|
||||
let remote_block_id = BlockId::Number(1);
|
||||
let (remote_block_header, remote_header_proof) = remote_client.header_proof_with_cht_size(&remote_block_id, 4).unwrap();
|
||||
|
||||
// check remote read proof locally
|
||||
let local_storage = InMemoryBlockchain::<Block>::new();
|
||||
let local_cht_root = cht::compute_root::<Header, BlakeTwo256, _>(4, 0, local_headers_hashes).unwrap();
|
||||
if insert_cht {
|
||||
local_storage.insert_cht_root(1, local_cht_root);
|
||||
}
|
||||
let local_checker = LightDataChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
(local_checker, local_cht_root, remote_block_header, remote_header_proof)
|
||||
}
|
||||
|
||||
fn header_with_computed_extrinsics_root(extrinsics: Vec<Extrinsic>) -> Header {
|
||||
use sp_trie::{TrieConfiguration, trie_types::Layout};
|
||||
let iter = extrinsics.iter().map(Encode::encode);
|
||||
let extrinsics_root = Layout::<BlakeTwo256>::ordered_trie_root(iter);
|
||||
|
||||
// only care about `extrinsics_root`
|
||||
Header::new(0, extrinsics_root, H256::zero(), H256::zero(), Default::default())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn storage_read_proof_is_generated_and_checked() {
|
||||
let (local_checker, remote_block_header, remote_read_proof, heap_pages) = prepare_for_read_proof_check();
|
||||
assert_eq!((&local_checker as &dyn FetchChecker<Block>).check_read_proof(&RemoteReadRequest::<Header> {
|
||||
block: remote_block_header.hash(),
|
||||
header: remote_block_header,
|
||||
keys: vec![well_known_keys::HEAP_PAGES.to_vec()],
|
||||
retry_count: None,
|
||||
}, remote_read_proof).unwrap().remove(well_known_keys::HEAP_PAGES).unwrap().unwrap()[0], heap_pages as u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn storage_child_read_proof_is_generated_and_checked() {
|
||||
let child_info = ChildInfo::new_default(&b"child1"[..]);
|
||||
let (
|
||||
local_checker,
|
||||
remote_block_header,
|
||||
remote_read_proof,
|
||||
result,
|
||||
) = prepare_for_read_child_proof_check();
|
||||
assert_eq!((&local_checker as &dyn FetchChecker<Block>).check_read_child_proof(
|
||||
&RemoteReadChildRequest::<Header> {
|
||||
block: remote_block_header.hash(),
|
||||
header: remote_block_header,
|
||||
storage_key: child_info.prefixed_storage_key(),
|
||||
keys: vec![b"key1".to_vec()],
|
||||
retry_count: None,
|
||||
},
|
||||
remote_read_proof
|
||||
).unwrap().remove(b"key1".as_ref()).unwrap().unwrap(), result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn header_proof_is_generated_and_checked() {
|
||||
let (local_checker, local_cht_root, remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true);
|
||||
assert_eq!((&local_checker as &dyn FetchChecker<Block>).check_header_proof(&RemoteHeaderRequest::<Header> {
|
||||
cht_root: local_cht_root,
|
||||
block: 1,
|
||||
retry_count: None,
|
||||
}, Some(remote_block_header.clone()), remote_header_proof).unwrap(), remote_block_header);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_header_proof_fails_if_cht_root_is_invalid() {
|
||||
let (local_checker, _, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true);
|
||||
remote_block_header.number = 100;
|
||||
assert!((&local_checker as &dyn FetchChecker<Block>).check_header_proof(&RemoteHeaderRequest::<Header> {
|
||||
cht_root: Default::default(),
|
||||
block: 1,
|
||||
retry_count: None,
|
||||
}, Some(remote_block_header.clone()), remote_header_proof).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_header_proof_fails_if_invalid_header_provided() {
|
||||
let (local_checker, local_cht_root, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true);
|
||||
remote_block_header.number = 100;
|
||||
assert!((&local_checker as &dyn FetchChecker<Block>).check_header_proof(&RemoteHeaderRequest::<Header> {
|
||||
cht_root: local_cht_root,
|
||||
block: 1,
|
||||
retry_count: None,
|
||||
}, Some(remote_block_header.clone()), remote_header_proof).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_proof_is_generated_and_checked_when_headers_are_not_pruned() {
|
||||
let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes();
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
let local_checker = &local_checker as &dyn FetchChecker<Block>;
|
||||
let max = remote_client.chain_info().best_number;
|
||||
let max_hash = remote_client.chain_info().best_hash;
|
||||
|
||||
for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() {
|
||||
let begin_hash = remote_client.block_hash(begin).unwrap().unwrap();
|
||||
let end_hash = remote_client.block_hash(end).unwrap().unwrap();
|
||||
|
||||
// 'fetch' changes proof from remote node
|
||||
let key = StorageKey(key);
|
||||
let remote_proof = remote_client.key_changes_proof(
|
||||
begin_hash, end_hash, begin_hash, max_hash, None, &key
|
||||
).unwrap();
|
||||
|
||||
// check proof on local client
|
||||
let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec();
|
||||
let config = ChangesTrieConfiguration::new(4, 2);
|
||||
let request = RemoteChangesRequest::<Header> {
|
||||
changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange {
|
||||
zero: (0, Default::default()),
|
||||
end: None,
|
||||
config: Some(config),
|
||||
}],
|
||||
first_block: (begin, begin_hash),
|
||||
last_block: (end, end_hash),
|
||||
max_block: (max, max_hash),
|
||||
tries_roots: (begin, begin_hash, local_roots_range),
|
||||
key: key.0,
|
||||
storage_key: None,
|
||||
retry_count: None,
|
||||
};
|
||||
let local_result = local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: remote_proof.proof,
|
||||
roots: remote_proof.roots,
|
||||
roots_proof: remote_proof.roots_proof,
|
||||
}).unwrap();
|
||||
|
||||
// ..and ensure that result is the same as on remote node
|
||||
match local_result == expected_result {
|
||||
true => (),
|
||||
false => panic!(format!("Failed test {}: local = {:?}, expected = {:?}",
|
||||
index, local_result, expected_result)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_proof_is_generated_and_checked_when_headers_are_pruned() {
|
||||
// we're testing this test case here:
|
||||
// (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]),
|
||||
let (remote_client, remote_roots, _) = prepare_client_with_key_changes();
|
||||
let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec();
|
||||
let dave = StorageKey(dave);
|
||||
|
||||
// 'fetch' changes proof from remote node:
|
||||
// we're fetching changes for range b1..b4
|
||||
// we do not know changes trie roots before b3 (i.e. we only know b3+b4)
|
||||
// but we have changes trie CHT root for b1...b4
|
||||
let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap();
|
||||
let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap();
|
||||
let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap();
|
||||
let remote_proof = remote_client.key_changes_proof_with_cht_size(
|
||||
b1, b4, b3, b4, None, &dave, 4
|
||||
).unwrap();
|
||||
|
||||
// prepare local checker, having a root of changes trie CHT#0
|
||||
let local_cht_root = cht::compute_root::<Header, BlakeTwo256, _>(4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap();
|
||||
let mut local_storage = DummyStorage::new();
|
||||
local_storage.changes_tries_cht_roots.insert(0, local_cht_root);
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(local_storage)),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
|
||||
// check proof on local client
|
||||
let config = ChangesTrieConfiguration::new(4, 2);
|
||||
let request = RemoteChangesRequest::<Header> {
|
||||
changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange {
|
||||
zero: (0, Default::default()),
|
||||
end: None,
|
||||
config: Some(config),
|
||||
}],
|
||||
first_block: (1, b1),
|
||||
last_block: (4, b4),
|
||||
max_block: (4, b4),
|
||||
tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]),
|
||||
storage_key: None,
|
||||
key: dave.0,
|
||||
retry_count: None,
|
||||
};
|
||||
let local_result = local_checker.check_changes_proof_with_cht_size(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: remote_proof.proof,
|
||||
roots: remote_proof.roots,
|
||||
roots_proof: remote_proof.roots_proof,
|
||||
}, 4).unwrap();
|
||||
|
||||
assert_eq!(local_result, vec![(4, 0), (1, 1), (1, 0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_changes_proof_fails_if_proof_is_wrong() {
|
||||
let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes();
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
let local_checker = &local_checker as &dyn FetchChecker<Block>;
|
||||
let max = remote_client.chain_info().best_number;
|
||||
let max_hash = remote_client.chain_info().best_hash;
|
||||
|
||||
let (begin, end, key, _) = test_cases[0].clone();
|
||||
let begin_hash = remote_client.block_hash(begin).unwrap().unwrap();
|
||||
let end_hash = remote_client.block_hash(end).unwrap().unwrap();
|
||||
|
||||
// 'fetch' changes proof from remote node
|
||||
let key = StorageKey(key);
|
||||
let remote_proof = remote_client.key_changes_proof(
|
||||
begin_hash, end_hash, begin_hash, max_hash, None, &key).unwrap();
|
||||
|
||||
let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec();
|
||||
let config = ChangesTrieConfiguration::new(4, 2);
|
||||
let request = RemoteChangesRequest::<Header> {
|
||||
changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange {
|
||||
zero: (0, Default::default()),
|
||||
end: None,
|
||||
config: Some(config),
|
||||
}],
|
||||
first_block: (begin, begin_hash),
|
||||
last_block: (end, end_hash),
|
||||
max_block: (max, max_hash),
|
||||
tries_roots: (begin, begin_hash, local_roots_range.clone()),
|
||||
storage_key: None,
|
||||
key: key.0,
|
||||
retry_count: None,
|
||||
};
|
||||
|
||||
// check proof on local client using max from the future
|
||||
assert!(local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block + 1,
|
||||
proof: remote_proof.proof.clone(),
|
||||
roots: remote_proof.roots.clone(),
|
||||
roots_proof: remote_proof.roots_proof.clone(),
|
||||
}).is_err());
|
||||
|
||||
// check proof on local client using broken proof
|
||||
assert!(local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: local_roots_range.clone().into_iter().map(|v| v.as_ref().to_vec()).collect(),
|
||||
roots: remote_proof.roots,
|
||||
roots_proof: remote_proof.roots_proof,
|
||||
}).is_err());
|
||||
|
||||
// extra roots proofs are provided
|
||||
assert!(local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: remote_proof.proof.clone(),
|
||||
roots: vec![(begin - 1, Default::default())].into_iter().collect(),
|
||||
roots_proof: StorageProof::empty(),
|
||||
}).is_err());
|
||||
assert!(local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: remote_proof.proof.clone(),
|
||||
roots: vec![(end + 1, Default::default())].into_iter().collect(),
|
||||
roots_proof: StorageProof::empty(),
|
||||
}).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_changes_tries_proof_fails_if_proof_is_wrong() {
|
||||
// we're testing this test case here:
|
||||
// (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]),
|
||||
let (remote_client, remote_roots, _) = prepare_client_with_key_changes();
|
||||
let local_cht_root = cht::compute_root::<Header, BlakeTwo256, _>(
|
||||
4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap();
|
||||
let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec();
|
||||
let dave = StorageKey(dave);
|
||||
|
||||
// 'fetch' changes proof from remote node:
|
||||
// we're fetching changes for range b1..b4
|
||||
// we do not know changes trie roots before b3 (i.e. we only know b3+b4)
|
||||
// but we have changes trie CHT root for b1...b4
|
||||
let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap();
|
||||
let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap();
|
||||
let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap();
|
||||
let remote_proof = remote_client.key_changes_proof_with_cht_size(
|
||||
b1, b4, b3, b4, None, &dave, 4
|
||||
).unwrap();
|
||||
|
||||
// fails when changes trie CHT is missing from the local db
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots,
|
||||
remote_proof.roots_proof.clone()).is_err());
|
||||
|
||||
// fails when proof is broken
|
||||
let mut local_storage = DummyStorage::new();
|
||||
local_storage.changes_tries_cht_roots.insert(0, local_cht_root);
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(local_storage)),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
let result = local_checker.check_changes_tries_proof(
|
||||
4, &remote_proof.roots, StorageProof::empty()
|
||||
);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_body_proof_faulty() {
|
||||
let header = header_with_computed_extrinsics_root(
|
||||
vec![Extrinsic::IncludeData(vec![1, 2, 3, 4])]
|
||||
);
|
||||
let block = Block::new(header.clone(), Vec::new());
|
||||
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
|
||||
let body_request = RemoteBodyRequest {
|
||||
header: header.clone(),
|
||||
retry_count: None,
|
||||
};
|
||||
|
||||
assert!(
|
||||
local_checker.check_body_proof(&body_request, block.extrinsics).is_err(),
|
||||
"vec![1, 2, 3, 4] != vec![]"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_body_proof_of_same_data_should_succeed() {
|
||||
let extrinsics = vec![Extrinsic::IncludeData(vec![1, 2, 3, 4, 5, 6, 7, 8, 255])];
|
||||
|
||||
let header = header_with_computed_extrinsics_root(extrinsics.clone());
|
||||
let block = Block::new(header.clone(), extrinsics);
|
||||
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
|
||||
let body_request = RemoteBodyRequest {
|
||||
header: header.clone(),
|
||||
retry_count: None,
|
||||
};
|
||||
|
||||
assert!(local_checker.check_body_proof(&body_request, block.extrinsics).is_ok());
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,11 +37,15 @@ use sc_service::{
|
||||
Role,
|
||||
Error,
|
||||
};
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sc_network::{multiaddr, Multiaddr};
|
||||
use sc_network::config::{NetworkConfiguration, TransportConfig};
|
||||
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
|
||||
use sp_transaction_pool::TransactionPool;
|
||||
|
||||
#[cfg(test)]
|
||||
mod client;
|
||||
|
||||
/// Maximum duration of single wait call.
|
||||
const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3);
|
||||
|
||||
@@ -462,15 +466,15 @@ pub fn sync<G, E, Fb, F, Lb, L, B, ExF, U>(
|
||||
}
|
||||
network.run_until_all_full(
|
||||
|_index, service|
|
||||
service.get().client().chain_info().best_number == (NUM_BLOCKS as u32).into(),
|
||||
service.get().client().info().best_number == (NUM_BLOCKS as u32).into(),
|
||||
|_index, service|
|
||||
service.get().client().chain_info().best_number == (NUM_BLOCKS as u32).into(),
|
||||
service.get().client().info().best_number == (NUM_BLOCKS as u32).into(),
|
||||
);
|
||||
|
||||
info!("Checking extrinsic propagation");
|
||||
let first_service = network.full_nodes[0].1.clone();
|
||||
let first_user_data = &network.full_nodes[0].2;
|
||||
let best_block = BlockId::number(first_service.get().client().chain_info().best_number);
|
||||
let best_block = BlockId::number(first_service.get().client().info().best_number);
|
||||
let extrinsic = extrinsic_factory(&first_service.get(), first_user_data);
|
||||
let source = sp_transaction_pool::TransactionSource::External;
|
||||
|
||||
@@ -523,9 +527,9 @@ pub fn consensus<G, E, Fb, F, Lb, L>(
|
||||
}
|
||||
network.run_until_all_full(
|
||||
|_index, service|
|
||||
service.get().client().chain_info().finalized_number >= (NUM_BLOCKS as u32 / 2).into(),
|
||||
service.get().client().info().finalized_number >= (NUM_BLOCKS as u32 / 2).into(),
|
||||
|_index, service|
|
||||
service.get().client().chain_info().best_number >= (NUM_BLOCKS as u32 / 2).into(),
|
||||
service.get().client().info().best_number >= (NUM_BLOCKS as u32 / 2).into(),
|
||||
);
|
||||
|
||||
info!("Adding more peers");
|
||||
@@ -545,8 +549,8 @@ pub fn consensus<G, E, Fb, F, Lb, L>(
|
||||
}
|
||||
network.run_until_all_full(
|
||||
|_index, service|
|
||||
service.get().client().chain_info().finalized_number >= (NUM_BLOCKS as u32).into(),
|
||||
service.get().client().info().finalized_number >= (NUM_BLOCKS as u32).into(),
|
||||
|_index, service|
|
||||
service.get().client().chain_info().best_number >= (NUM_BLOCKS as u32).into(),
|
||||
service.get().client().info().best_number >= (NUM_BLOCKS as u32).into(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,833 +0,0 @@
|
||||
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Light client data fetcher. Fetches requested data from remote full nodes.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_core::{convert_hash, traits::CodeExecutor};
|
||||
use sp_core::storage::{ChildInfo, ChildType};
|
||||
use sp_runtime::traits::{
|
||||
Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor,
|
||||
AtLeast32Bit, CheckedConversion,
|
||||
};
|
||||
use sp_state_machine::{
|
||||
ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange,
|
||||
InMemoryChangesTrieStorage, TrieBackend, read_proof_check, key_changes_proof_check_with_db,
|
||||
read_child_proof_check, CloneableSpawn,
|
||||
};
|
||||
pub use sp_state_machine::StorageProof;
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
|
||||
use crate::cht;
|
||||
pub use sc_client_api::{
|
||||
light::{
|
||||
RemoteCallRequest, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest,
|
||||
RemoteChangesRequest, ChangesProof, RemoteBodyRequest, Fetcher, FetchChecker,
|
||||
Storage as BlockchainStorage,
|
||||
},
|
||||
};
|
||||
use crate::light::blockchain::{Blockchain};
|
||||
use crate::light::call_executor::check_execution_proof;
|
||||
|
||||
/// Remote data checker.
|
||||
pub struct LightDataChecker<E, H, B: BlockT, S: BlockchainStorage<B>> {
|
||||
blockchain: Arc<Blockchain<S>>,
|
||||
executor: E,
|
||||
spawn_handle: Box<dyn CloneableSpawn>,
|
||||
_hasher: PhantomData<(B, H)>,
|
||||
}
|
||||
|
||||
impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
|
||||
/// Create new light data checker.
|
||||
pub fn new(blockchain: Arc<Blockchain<S>>, executor: E, spawn_handle: Box<dyn CloneableSpawn>) -> Self {
|
||||
Self {
|
||||
blockchain, executor, spawn_handle, _hasher: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
/// Check remote changes query proof assuming that CHT-s are of given size.
|
||||
fn check_changes_proof_with_cht_size(
|
||||
&self,
|
||||
request: &RemoteChangesRequest<B::Header>,
|
||||
remote_proof: ChangesProof<B::Header>,
|
||||
cht_size: NumberFor<B>,
|
||||
) -> ClientResult<Vec<(NumberFor<B>, u32)>>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Ord + codec::Codec,
|
||||
{
|
||||
// since we need roots of all changes tries for the range begin..max
|
||||
// => remote node can't use max block greater that one that we have passed
|
||||
if remote_proof.max_block > request.max_block.0 || remote_proof.max_block < request.last_block.0 {
|
||||
return Err(ClientError::ChangesTrieAccessFailed(format!(
|
||||
"Invalid max_block used by the remote node: {}. Local: {}..{}..{}",
|
||||
remote_proof.max_block, request.first_block.0, request.last_block.0, request.max_block.0,
|
||||
)).into());
|
||||
}
|
||||
|
||||
// check if remote node has responded with extra changes trie roots proofs
|
||||
// all changes tries roots must be in range [request.first_block.0; request.tries_roots.0)
|
||||
let is_extra_first_root = remote_proof.roots.keys().next()
|
||||
.map(|first_root| *first_root < request.first_block.0
|
||||
|| *first_root >= request.tries_roots.0)
|
||||
.unwrap_or(false);
|
||||
let is_extra_last_root = remote_proof.roots.keys().next_back()
|
||||
.map(|last_root| *last_root >= request.tries_roots.0)
|
||||
.unwrap_or(false);
|
||||
if is_extra_first_root || is_extra_last_root {
|
||||
return Err(ClientError::ChangesTrieAccessFailed(format!(
|
||||
"Extra changes tries roots proofs provided by the remote node: [{:?}..{:?}]. Expected in range: [{}; {})",
|
||||
remote_proof.roots.keys().next(), remote_proof.roots.keys().next_back(),
|
||||
request.first_block.0, request.tries_roots.0,
|
||||
)).into());
|
||||
}
|
||||
|
||||
// if request has been composed when some required headers were already pruned
|
||||
// => remote node has sent us CHT-based proof of required changes tries roots
|
||||
// => check that this proof is correct before proceeding with changes proof
|
||||
let remote_max_block = remote_proof.max_block;
|
||||
let remote_roots = remote_proof.roots;
|
||||
let remote_roots_proof = remote_proof.roots_proof;
|
||||
let remote_proof = remote_proof.proof;
|
||||
if !remote_roots.is_empty() {
|
||||
self.check_changes_tries_proof(
|
||||
cht_size,
|
||||
&remote_roots,
|
||||
remote_roots_proof,
|
||||
)?;
|
||||
}
|
||||
|
||||
// and now check the key changes proof + get the changes
|
||||
let mut result = Vec::new();
|
||||
let proof_storage = InMemoryChangesTrieStorage::with_proof(remote_proof);
|
||||
for config_range in &request.changes_trie_configs {
|
||||
let result_range = key_changes_proof_check_with_db::<H, _>(
|
||||
ChangesTrieConfigurationRange {
|
||||
config: config_range.config.as_ref().ok_or(ClientError::ChangesTriesNotSupported)?,
|
||||
zero: config_range.zero.0,
|
||||
end: config_range.end.map(|(n, _)| n),
|
||||
},
|
||||
&RootsStorage {
|
||||
roots: (request.tries_roots.0, &request.tries_roots.2),
|
||||
prev_roots: &remote_roots,
|
||||
},
|
||||
&proof_storage,
|
||||
request.first_block.0,
|
||||
&ChangesTrieAnchorBlockId {
|
||||
hash: convert_hash(&request.last_block.1),
|
||||
number: request.last_block.0,
|
||||
},
|
||||
remote_max_block,
|
||||
request.storage_key.as_ref(),
|
||||
&request.key)
|
||||
.map_err(|err| ClientError::ChangesTrieAccessFailed(err))?;
|
||||
result.extend(result_range);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Check CHT-based proof for changes tries roots.
|
||||
fn check_changes_tries_proof(
|
||||
&self,
|
||||
cht_size: NumberFor<B>,
|
||||
remote_roots: &BTreeMap<NumberFor<B>, B::Hash>,
|
||||
remote_roots_proof: StorageProof,
|
||||
) -> ClientResult<()>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Ord + codec::Codec,
|
||||
{
|
||||
// all the checks are sharing the same storage
|
||||
let storage = remote_roots_proof.into_memory_db();
|
||||
|
||||
// remote_roots.keys() are sorted => we can use this to group changes tries roots
|
||||
// that are belongs to the same CHT
|
||||
let blocks = remote_roots.keys().cloned();
|
||||
cht::for_each_cht_group::<B::Header, _, _, _>(cht_size, blocks, |mut storage, _, cht_blocks| {
|
||||
// get local changes trie CHT root for given CHT
|
||||
// it should be there, because it is never pruned AND request has been composed
|
||||
// when required header has been pruned (=> replaced with CHT)
|
||||
let first_block = cht_blocks.first().cloned()
|
||||
.expect("for_each_cht_group never calls callback with empty groups");
|
||||
let local_cht_root = self.blockchain.storage().changes_trie_cht_root(cht_size, first_block)?
|
||||
.ok_or(ClientError::InvalidCHTProof)?;
|
||||
|
||||
// check changes trie root for every block within CHT range
|
||||
for block in cht_blocks {
|
||||
// check if the proofs storage contains the root
|
||||
// normally this happens in when the proving backend is created, but since
|
||||
// we share the storage for multiple checks, do it here
|
||||
let mut cht_root = H::Out::default();
|
||||
cht_root.as_mut().copy_from_slice(local_cht_root.as_ref());
|
||||
if !storage.contains(&cht_root, EMPTY_PREFIX) {
|
||||
return Err(ClientError::InvalidCHTProof.into());
|
||||
}
|
||||
|
||||
// check proof for single changes trie root
|
||||
let proving_backend = TrieBackend::new(storage, cht_root);
|
||||
let remote_changes_trie_root = remote_roots[&block];
|
||||
cht::check_proof_on_proving_backend::<B::Header, H>(
|
||||
local_cht_root,
|
||||
block,
|
||||
remote_changes_trie_root,
|
||||
&proving_backend,
|
||||
)?;
|
||||
|
||||
// and return the storage to use in following checks
|
||||
storage = proving_backend.into_storage();
|
||||
}
|
||||
|
||||
Ok(storage)
|
||||
}, storage)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
|
||||
where
|
||||
Block: BlockT,
|
||||
E: CodeExecutor + Clone + 'static,
|
||||
H: Hasher,
|
||||
H::Out: Ord + codec::Codec + 'static,
|
||||
S: BlockchainStorage<Block>,
|
||||
{
|
||||
fn check_header_proof(
|
||||
&self,
|
||||
request: &RemoteHeaderRequest<Block::Header>,
|
||||
remote_header: Option<Block::Header>,
|
||||
remote_proof: StorageProof,
|
||||
) -> ClientResult<Block::Header> {
|
||||
let remote_header = remote_header.ok_or_else(||
|
||||
ClientError::from(ClientError::InvalidCHTProof))?;
|
||||
let remote_header_hash = remote_header.hash();
|
||||
cht::check_proof::<Block::Header, H>(
|
||||
request.cht_root,
|
||||
request.block,
|
||||
remote_header_hash,
|
||||
remote_proof,
|
||||
).map(|_| remote_header)
|
||||
}
|
||||
|
||||
fn check_read_proof(
|
||||
&self,
|
||||
request: &RemoteReadRequest<Block::Header>,
|
||||
remote_proof: StorageProof,
|
||||
) -> ClientResult<HashMap<Vec<u8>, Option<Vec<u8>>>> {
|
||||
read_proof_check::<H, _>(
|
||||
convert_hash(request.header.state_root()),
|
||||
remote_proof,
|
||||
request.keys.iter(),
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn check_read_child_proof(
|
||||
&self,
|
||||
request: &RemoteReadChildRequest<Block::Header>,
|
||||
remote_proof: StorageProof,
|
||||
) -> ClientResult<HashMap<Vec<u8>, Option<Vec<u8>>>> {
|
||||
let child_info = match ChildType::from_prefixed_key(&request.storage_key) {
|
||||
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
|
||||
None => return Err("Invalid child type".into()),
|
||||
};
|
||||
read_child_proof_check::<H, _>(
|
||||
convert_hash(request.header.state_root()),
|
||||
remote_proof,
|
||||
&child_info,
|
||||
request.keys.iter(),
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn check_execution_proof(
|
||||
&self,
|
||||
request: &RemoteCallRequest<Block::Header>,
|
||||
remote_proof: StorageProof,
|
||||
) -> ClientResult<Vec<u8>> {
|
||||
check_execution_proof::<_, _, H>(
|
||||
&self.executor,
|
||||
self.spawn_handle.clone(),
|
||||
request,
|
||||
remote_proof,
|
||||
)
|
||||
}
|
||||
|
||||
fn check_changes_proof(
|
||||
&self,
|
||||
request: &RemoteChangesRequest<Block::Header>,
|
||||
remote_proof: ChangesProof<Block::Header>
|
||||
) -> ClientResult<Vec<(NumberFor<Block>, u32)>> {
|
||||
self.check_changes_proof_with_cht_size(request, remote_proof, cht::size())
|
||||
}
|
||||
|
||||
fn check_body_proof(
|
||||
&self,
|
||||
request: &RemoteBodyRequest<Block::Header>,
|
||||
body: Vec<Block::Extrinsic>
|
||||
) -> ClientResult<Vec<Block::Extrinsic>> {
|
||||
// TODO: #2621
|
||||
let extrinsics_root = HashFor::<Block>::ordered_trie_root(
|
||||
body.iter().map(Encode::encode).collect(),
|
||||
);
|
||||
if *request.header.extrinsics_root() == extrinsics_root {
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(format!("RemoteBodyRequest: invalid extrinsics root expected: {} but got {}",
|
||||
*request.header.extrinsics_root(),
|
||||
extrinsics_root,
|
||||
).into())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// A view of BTreeMap<Number, Hash> as a changes trie roots storage.
|
||||
struct RootsStorage<'a, Number: AtLeast32Bit, Hash: 'a> {
|
||||
roots: (Number, &'a [Hash]),
|
||||
prev_roots: &'a BTreeMap<Number, Hash>,
|
||||
}
|
||||
|
||||
impl<'a, H, Number, Hash> ChangesTrieRootsStorage<H, Number> for RootsStorage<'a, Number, Hash>
|
||||
where
|
||||
H: Hasher,
|
||||
Number: std::fmt::Display + std::hash::Hash + Clone + AtLeast32Bit + Encode + Decode + Send + Sync + 'static,
|
||||
Hash: 'a + Send + Sync + Clone + AsRef<[u8]>,
|
||||
{
|
||||
fn build_anchor(
|
||||
&self,
|
||||
_hash: H::Out,
|
||||
) -> Result<sp_state_machine::ChangesTrieAnchorBlockId<H::Out, Number>, String> {
|
||||
Err("build_anchor is only called when building block".into())
|
||||
}
|
||||
|
||||
fn root(
|
||||
&self,
|
||||
_anchor: &ChangesTrieAnchorBlockId<H::Out, Number>,
|
||||
block: Number,
|
||||
) -> Result<Option<H::Out>, String> {
|
||||
// we can't ask for roots from parallel forks here => ignore anchor
|
||||
let root = if block < self.roots.0 {
|
||||
self.prev_roots.get(&Number::unique_saturated_from(block)).cloned()
|
||||
} else {
|
||||
let index: Option<usize> = block.checked_sub(&self.roots.0).and_then(|index| index.checked_into());
|
||||
match index {
|
||||
Some(index) => self.roots.1.get(index as usize).cloned(),
|
||||
None => None,
|
||||
}
|
||||
};
|
||||
|
||||
Ok(root.map(|root| {
|
||||
let mut hasher_root: H::Out = Default::default();
|
||||
hasher_root.as_mut().copy_from_slice(root.as_ref());
|
||||
hasher_root
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use codec::Decode;
|
||||
use crate::client::tests::prepare_client_with_key_changes;
|
||||
use sc_executor::{NativeExecutor, WasmExecutionMethod};
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use sc_client_api::backend::NewBlockState;
|
||||
use substrate_test_runtime_client::{
|
||||
blockchain::HeaderBackend, AccountKeyring, ClientBlockImportExt,
|
||||
runtime::{self, Hash, Block, Header, Extrinsic},
|
||||
tasks_executor,
|
||||
};
|
||||
use sp_consensus::BlockOrigin;
|
||||
|
||||
use crate::in_mem::Blockchain as InMemoryBlockchain;
|
||||
use crate::light::fetcher::{FetchChecker, LightDataChecker, RemoteHeaderRequest};
|
||||
use crate::light::blockchain::tests::{DummyStorage, DummyBlockchain};
|
||||
use sp_core::{blake2_256, ChangesTrieConfiguration, H256};
|
||||
use sp_core::storage::{well_known_keys, StorageKey, ChildInfo};
|
||||
use sp_runtime::{generic::BlockId, traits::BlakeTwo256};
|
||||
use sp_state_machine::Backend;
|
||||
use super::*;
|
||||
use sc_client_api::{StorageProvider, ProofProvider};
|
||||
use sc_block_builder::BlockBuilderProvider;
|
||||
|
||||
type TestChecker = LightDataChecker<
|
||||
NativeExecutor<substrate_test_runtime_client::LocalExecutor>,
|
||||
BlakeTwo256,
|
||||
Block,
|
||||
DummyStorage,
|
||||
>;
|
||||
|
||||
fn local_executor() -> NativeExecutor<substrate_test_runtime_client::LocalExecutor> {
|
||||
NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8)
|
||||
}
|
||||
|
||||
fn prepare_for_read_proof_check() -> (TestChecker, Header, StorageProof, u32) {
|
||||
// prepare remote client
|
||||
let remote_client = substrate_test_runtime_client::new();
|
||||
let remote_block_id = BlockId::Number(0);
|
||||
let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap();
|
||||
let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap();
|
||||
remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap()
|
||||
.storage_root(::std::iter::empty()).0.into();
|
||||
|
||||
// 'fetch' read proof from remote node
|
||||
let heap_pages = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::HEAP_PAGES.to_vec()))
|
||||
.unwrap()
|
||||
.and_then(|v| Decode::decode(&mut &v.0[..]).ok()).unwrap();
|
||||
let remote_read_proof = remote_client.read_proof(
|
||||
&remote_block_id,
|
||||
&mut std::iter::once(well_known_keys::HEAP_PAGES),
|
||||
).unwrap();
|
||||
|
||||
// check remote read proof locally
|
||||
let local_storage = InMemoryBlockchain::<Block>::new();
|
||||
local_storage.insert(
|
||||
remote_block_hash,
|
||||
remote_block_header.clone(),
|
||||
None,
|
||||
None,
|
||||
NewBlockState::Final,
|
||||
).unwrap();
|
||||
let local_checker = LightDataChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
(local_checker, remote_block_header, remote_read_proof, heap_pages)
|
||||
}
|
||||
|
||||
fn prepare_for_read_child_proof_check() -> (TestChecker, Header, StorageProof, Vec<u8>) {
|
||||
use substrate_test_runtime_client::DefaultTestClientBuilderExt;
|
||||
use substrate_test_runtime_client::TestClientBuilderExt;
|
||||
let child_info = ChildInfo::new_default(b"child1");
|
||||
let child_info = &child_info;
|
||||
// prepare remote client
|
||||
let remote_client = substrate_test_runtime_client::TestClientBuilder::new()
|
||||
.add_extra_child_storage(
|
||||
child_info,
|
||||
b"key1".to_vec(),
|
||||
b"value1".to_vec(),
|
||||
).build();
|
||||
let remote_block_id = BlockId::Number(0);
|
||||
let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap();
|
||||
let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap();
|
||||
remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap()
|
||||
.storage_root(::std::iter::empty()).0.into();
|
||||
|
||||
// 'fetch' child read proof from remote node
|
||||
let child_value = remote_client.child_storage(
|
||||
&remote_block_id,
|
||||
child_info,
|
||||
&StorageKey(b"key1".to_vec()),
|
||||
).unwrap().unwrap().0;
|
||||
assert_eq!(b"value1"[..], child_value[..]);
|
||||
let remote_read_proof = remote_client.read_child_proof(
|
||||
&remote_block_id,
|
||||
child_info,
|
||||
&mut std::iter::once("key1".as_bytes()),
|
||||
).unwrap();
|
||||
|
||||
// check locally
|
||||
let local_storage = InMemoryBlockchain::<Block>::new();
|
||||
local_storage.insert(
|
||||
remote_block_hash,
|
||||
remote_block_header.clone(),
|
||||
None,
|
||||
None,
|
||||
NewBlockState::Final,
|
||||
).unwrap();
|
||||
let local_checker = LightDataChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
(local_checker, remote_block_header, remote_read_proof, child_value)
|
||||
}
|
||||
|
||||
fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, StorageProof) {
|
||||
// prepare remote client
|
||||
let mut remote_client = substrate_test_runtime_client::new();
|
||||
let mut local_headers_hashes = Vec::new();
|
||||
for i in 0..4 {
|
||||
let block = remote_client.new_block(Default::default()).unwrap().build().unwrap().block;
|
||||
remote_client.import(BlockOrigin::Own, block).unwrap();
|
||||
local_headers_hashes.push(
|
||||
remote_client.block_hash(i + 1)
|
||||
.map_err(|_| ClientError::Backend("TestError".into()))
|
||||
);
|
||||
}
|
||||
|
||||
// 'fetch' header proof from remote node
|
||||
let remote_block_id = BlockId::Number(1);
|
||||
let (remote_block_header, remote_header_proof) = remote_client.header_proof_with_cht_size(&remote_block_id, 4).unwrap();
|
||||
|
||||
// check remote read proof locally
|
||||
let local_storage = InMemoryBlockchain::<Block>::new();
|
||||
let local_cht_root = cht::compute_root::<Header, BlakeTwo256, _>(4, 0, local_headers_hashes).unwrap();
|
||||
if insert_cht {
|
||||
local_storage.insert_cht_root(1, local_cht_root);
|
||||
}
|
||||
let local_checker = LightDataChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
(local_checker, local_cht_root, remote_block_header, remote_header_proof)
|
||||
}
|
||||
|
||||
fn header_with_computed_extrinsics_root(extrinsics: Vec<Extrinsic>) -> Header {
|
||||
use sp_trie::{TrieConfiguration, trie_types::Layout};
|
||||
let iter = extrinsics.iter().map(Encode::encode);
|
||||
let extrinsics_root = Layout::<BlakeTwo256>::ordered_trie_root(iter);
|
||||
|
||||
// only care about `extrinsics_root`
|
||||
Header::new(0, extrinsics_root, H256::zero(), H256::zero(), Default::default())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn storage_read_proof_is_generated_and_checked() {
|
||||
let (local_checker, remote_block_header, remote_read_proof, heap_pages) = prepare_for_read_proof_check();
|
||||
assert_eq!((&local_checker as &dyn FetchChecker<Block>).check_read_proof(&RemoteReadRequest::<Header> {
|
||||
block: remote_block_header.hash(),
|
||||
header: remote_block_header,
|
||||
keys: vec![well_known_keys::HEAP_PAGES.to_vec()],
|
||||
retry_count: None,
|
||||
}, remote_read_proof).unwrap().remove(well_known_keys::HEAP_PAGES).unwrap().unwrap()[0], heap_pages as u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn storage_child_read_proof_is_generated_and_checked() {
|
||||
let child_info = ChildInfo::new_default(&b"child1"[..]);
|
||||
let (
|
||||
local_checker,
|
||||
remote_block_header,
|
||||
remote_read_proof,
|
||||
result,
|
||||
) = prepare_for_read_child_proof_check();
|
||||
assert_eq!((&local_checker as &dyn FetchChecker<Block>).check_read_child_proof(
|
||||
&RemoteReadChildRequest::<Header> {
|
||||
block: remote_block_header.hash(),
|
||||
header: remote_block_header,
|
||||
storage_key: child_info.prefixed_storage_key(),
|
||||
keys: vec![b"key1".to_vec()],
|
||||
retry_count: None,
|
||||
},
|
||||
remote_read_proof
|
||||
).unwrap().remove(b"key1".as_ref()).unwrap().unwrap(), result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn header_proof_is_generated_and_checked() {
|
||||
let (local_checker, local_cht_root, remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true);
|
||||
assert_eq!((&local_checker as &dyn FetchChecker<Block>).check_header_proof(&RemoteHeaderRequest::<Header> {
|
||||
cht_root: local_cht_root,
|
||||
block: 1,
|
||||
retry_count: None,
|
||||
}, Some(remote_block_header.clone()), remote_header_proof).unwrap(), remote_block_header);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_header_proof_fails_if_cht_root_is_invalid() {
|
||||
let (local_checker, _, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true);
|
||||
remote_block_header.number = 100;
|
||||
assert!((&local_checker as &dyn FetchChecker<Block>).check_header_proof(&RemoteHeaderRequest::<Header> {
|
||||
cht_root: Default::default(),
|
||||
block: 1,
|
||||
retry_count: None,
|
||||
}, Some(remote_block_header.clone()), remote_header_proof).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_header_proof_fails_if_invalid_header_provided() {
|
||||
let (local_checker, local_cht_root, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true);
|
||||
remote_block_header.number = 100;
|
||||
assert!((&local_checker as &dyn FetchChecker<Block>).check_header_proof(&RemoteHeaderRequest::<Header> {
|
||||
cht_root: local_cht_root,
|
||||
block: 1,
|
||||
retry_count: None,
|
||||
}, Some(remote_block_header.clone()), remote_header_proof).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_proof_is_generated_and_checked_when_headers_are_not_pruned() {
|
||||
let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes();
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
let local_checker = &local_checker as &dyn FetchChecker<Block>;
|
||||
let max = remote_client.chain_info().best_number;
|
||||
let max_hash = remote_client.chain_info().best_hash;
|
||||
|
||||
for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() {
|
||||
let begin_hash = remote_client.block_hash(begin).unwrap().unwrap();
|
||||
let end_hash = remote_client.block_hash(end).unwrap().unwrap();
|
||||
|
||||
// 'fetch' changes proof from remote node
|
||||
let key = StorageKey(key);
|
||||
let remote_proof = remote_client.key_changes_proof(
|
||||
begin_hash, end_hash, begin_hash, max_hash, None, &key
|
||||
).unwrap();
|
||||
|
||||
// check proof on local client
|
||||
let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec();
|
||||
let config = ChangesTrieConfiguration::new(4, 2);
|
||||
let request = RemoteChangesRequest::<Header> {
|
||||
changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange {
|
||||
zero: (0, Default::default()),
|
||||
end: None,
|
||||
config: Some(config),
|
||||
}],
|
||||
first_block: (begin, begin_hash),
|
||||
last_block: (end, end_hash),
|
||||
max_block: (max, max_hash),
|
||||
tries_roots: (begin, begin_hash, local_roots_range),
|
||||
key: key.0,
|
||||
storage_key: None,
|
||||
retry_count: None,
|
||||
};
|
||||
let local_result = local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: remote_proof.proof,
|
||||
roots: remote_proof.roots,
|
||||
roots_proof: remote_proof.roots_proof,
|
||||
}).unwrap();
|
||||
|
||||
// ..and ensure that result is the same as on remote node
|
||||
match local_result == expected_result {
|
||||
true => (),
|
||||
false => panic!(format!("Failed test {}: local = {:?}, expected = {:?}",
|
||||
index, local_result, expected_result)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_proof_is_generated_and_checked_when_headers_are_pruned() {
|
||||
// we're testing this test case here:
|
||||
// (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]),
|
||||
let (remote_client, remote_roots, _) = prepare_client_with_key_changes();
|
||||
let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec();
|
||||
let dave = StorageKey(dave);
|
||||
|
||||
// 'fetch' changes proof from remote node:
|
||||
// we're fetching changes for range b1..b4
|
||||
// we do not know changes trie roots before b3 (i.e. we only know b3+b4)
|
||||
// but we have changes trie CHT root for b1...b4
|
||||
let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap();
|
||||
let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap();
|
||||
let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap();
|
||||
let remote_proof = remote_client.key_changes_proof_with_cht_size(
|
||||
b1, b4, b3, b4, None, &dave, 4
|
||||
).unwrap();
|
||||
|
||||
// prepare local checker, having a root of changes trie CHT#0
|
||||
let local_cht_root = cht::compute_root::<Header, BlakeTwo256, _>(4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap();
|
||||
let mut local_storage = DummyStorage::new();
|
||||
local_storage.changes_tries_cht_roots.insert(0, local_cht_root);
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(local_storage)),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
|
||||
// check proof on local client
|
||||
let config = ChangesTrieConfiguration::new(4, 2);
|
||||
let request = RemoteChangesRequest::<Header> {
|
||||
changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange {
|
||||
zero: (0, Default::default()),
|
||||
end: None,
|
||||
config: Some(config),
|
||||
}],
|
||||
first_block: (1, b1),
|
||||
last_block: (4, b4),
|
||||
max_block: (4, b4),
|
||||
tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]),
|
||||
storage_key: None,
|
||||
key: dave.0,
|
||||
retry_count: None,
|
||||
};
|
||||
let local_result = local_checker.check_changes_proof_with_cht_size(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: remote_proof.proof,
|
||||
roots: remote_proof.roots,
|
||||
roots_proof: remote_proof.roots_proof,
|
||||
}, 4).unwrap();
|
||||
|
||||
assert_eq!(local_result, vec![(4, 0), (1, 1), (1, 0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_changes_proof_fails_if_proof_is_wrong() {
|
||||
let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes();
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
let local_checker = &local_checker as &dyn FetchChecker<Block>;
|
||||
let max = remote_client.chain_info().best_number;
|
||||
let max_hash = remote_client.chain_info().best_hash;
|
||||
|
||||
let (begin, end, key, _) = test_cases[0].clone();
|
||||
let begin_hash = remote_client.block_hash(begin).unwrap().unwrap();
|
||||
let end_hash = remote_client.block_hash(end).unwrap().unwrap();
|
||||
|
||||
// 'fetch' changes proof from remote node
|
||||
let key = StorageKey(key);
|
||||
let remote_proof = remote_client.key_changes_proof(
|
||||
begin_hash, end_hash, begin_hash, max_hash, None, &key).unwrap();
|
||||
|
||||
let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec();
|
||||
let config = ChangesTrieConfiguration::new(4, 2);
|
||||
let request = RemoteChangesRequest::<Header> {
|
||||
changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange {
|
||||
zero: (0, Default::default()),
|
||||
end: None,
|
||||
config: Some(config),
|
||||
}],
|
||||
first_block: (begin, begin_hash),
|
||||
last_block: (end, end_hash),
|
||||
max_block: (max, max_hash),
|
||||
tries_roots: (begin, begin_hash, local_roots_range.clone()),
|
||||
storage_key: None,
|
||||
key: key.0,
|
||||
retry_count: None,
|
||||
};
|
||||
|
||||
// check proof on local client using max from the future
|
||||
assert!(local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block + 1,
|
||||
proof: remote_proof.proof.clone(),
|
||||
roots: remote_proof.roots.clone(),
|
||||
roots_proof: remote_proof.roots_proof.clone(),
|
||||
}).is_err());
|
||||
|
||||
// check proof on local client using broken proof
|
||||
assert!(local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: local_roots_range.clone().into_iter().map(|v| v.as_ref().to_vec()).collect(),
|
||||
roots: remote_proof.roots,
|
||||
roots_proof: remote_proof.roots_proof,
|
||||
}).is_err());
|
||||
|
||||
// extra roots proofs are provided
|
||||
assert!(local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: remote_proof.proof.clone(),
|
||||
roots: vec![(begin - 1, Default::default())].into_iter().collect(),
|
||||
roots_proof: StorageProof::empty(),
|
||||
}).is_err());
|
||||
assert!(local_checker.check_changes_proof(&request, ChangesProof {
|
||||
max_block: remote_proof.max_block,
|
||||
proof: remote_proof.proof.clone(),
|
||||
roots: vec![(end + 1, Default::default())].into_iter().collect(),
|
||||
roots_proof: StorageProof::empty(),
|
||||
}).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_changes_tries_proof_fails_if_proof_is_wrong() {
|
||||
// we're testing this test case here:
|
||||
// (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]),
|
||||
let (remote_client, remote_roots, _) = prepare_client_with_key_changes();
|
||||
let local_cht_root = cht::compute_root::<Header, BlakeTwo256, _>(
|
||||
4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap();
|
||||
let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec();
|
||||
let dave = StorageKey(dave);
|
||||
|
||||
// 'fetch' changes proof from remote node:
|
||||
// we're fetching changes for range b1..b4
|
||||
// we do not know changes trie roots before b3 (i.e. we only know b3+b4)
|
||||
// but we have changes trie CHT root for b1...b4
|
||||
let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap();
|
||||
let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap();
|
||||
let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap();
|
||||
let remote_proof = remote_client.key_changes_proof_with_cht_size(
|
||||
b1, b4, b3, b4, None, &dave, 4
|
||||
).unwrap();
|
||||
|
||||
// fails when changes trie CHT is missing from the local db
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots,
|
||||
remote_proof.roots_proof.clone()).is_err());
|
||||
|
||||
// fails when proof is broken
|
||||
let mut local_storage = DummyStorage::new();
|
||||
local_storage.changes_tries_cht_roots.insert(0, local_cht_root);
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(local_storage)),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
let result = local_checker.check_changes_tries_proof(
|
||||
4, &remote_proof.roots, StorageProof::empty()
|
||||
);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_body_proof_faulty() {
|
||||
let header = header_with_computed_extrinsics_root(
|
||||
vec![Extrinsic::IncludeData(vec![1, 2, 3, 4])]
|
||||
);
|
||||
let block = Block::new(header.clone(), Vec::new());
|
||||
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
|
||||
let body_request = RemoteBodyRequest {
|
||||
header: header.clone(),
|
||||
retry_count: None,
|
||||
};
|
||||
|
||||
assert!(
|
||||
local_checker.check_body_proof(&body_request, block.extrinsics).is_err(),
|
||||
"vec![1, 2, 3, 4] != vec![]"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_body_proof_of_same_data_should_succeed() {
|
||||
let extrinsics = vec![Extrinsic::IncludeData(vec![1, 2, 3, 4, 5, 6, 7, 8, 255])];
|
||||
|
||||
let header = header_with_computed_extrinsics_root(extrinsics.clone());
|
||||
let block = Block::new(header.clone(), extrinsics);
|
||||
|
||||
let local_checker = TestChecker::new(
|
||||
Arc::new(DummyBlockchain::new(DummyStorage::new())),
|
||||
local_executor(),
|
||||
tasks_executor(),
|
||||
);
|
||||
|
||||
let body_request = RemoteBodyRequest {
|
||||
header: header.clone(),
|
||||
retry_count: None,
|
||||
};
|
||||
|
||||
assert!(local_checker.check_body_proof(&body_request, block.extrinsics).is_ok());
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ mock_impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
type TestClient = substrate_test_runtime_client::sc_client::Client<
|
||||
type TestClient = substrate_test_runtime_client::client::Client<
|
||||
substrate_test_runtime_client::Backend,
|
||||
substrate_test_runtime_client::Executor,
|
||||
Block,
|
||||
|
||||
@@ -23,5 +23,5 @@ error[E0277]: the trait bound `u32: std::convert::From<std::string::String>` is
|
||||
<u32 as std::convert::From<bool>>
|
||||
<u32 as std::convert::From<char>>
|
||||
<u32 as std::convert::From<h2::frame::reason::Reason>>
|
||||
<u32 as std::convert::From<h2::frame::stream_id::StreamId>>
|
||||
and 16 others
|
||||
<u32 as std::convert::From<h2::frame::reason::Reason>>
|
||||
and 18 others
|
||||
|
||||
@@ -13,10 +13,11 @@ targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../client/api" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../client/" }
|
||||
sc-client-db = { version = "0.8.0-dev", features = ["test-helpers"], path = "../../client/db" }
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "../../client/executor" }
|
||||
sc-consensus = { version = "0.8.0-dev", path = "../../client/consensus/common" }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, features = ["test-helpers"], path = "../../client/service" }
|
||||
futures = "0.3.4"
|
||||
hash-db = "0.15.2"
|
||||
sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" }
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
//! Client extension for tests.
|
||||
|
||||
use sc_client::{self, Client};
|
||||
use sc_service::client::Client;
|
||||
use sc_client_api::backend::Finalizer;
|
||||
use sp_consensus::{
|
||||
BlockImportParams, BlockImport, BlockOrigin, Error as ConsensusError,
|
||||
@@ -64,7 +64,7 @@ pub trait ClientBlockImportExt<Block: BlockT>: Sized {
|
||||
impl<B, E, RA, Block> ClientExt<Block> for Client<B, E, Block, RA>
|
||||
where
|
||||
B: sc_client_api::backend::Backend<Block>,
|
||||
E: sc_client::CallExecutor<Block> + 'static,
|
||||
E: sc_client_api::CallExecutor<Block> + 'static,
|
||||
Self: BlockImport<Block, Error = ConsensusError>,
|
||||
Block: BlockT,
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
pub mod client_ext;
|
||||
|
||||
pub use sc_client::{blockchain, self};
|
||||
pub use sc_client_api::{
|
||||
execution_extensions::{ExecutionStrategies, ExecutionExtensions},
|
||||
ForkBlocks, BadBlocks, CloneableSpawn,
|
||||
@@ -36,16 +35,17 @@ pub use sp_keyring::{
|
||||
pub use sp_core::{traits::BareCryptoStorePtr, tasks::executor as tasks_executor};
|
||||
pub use sp_runtime::{Storage, StorageChild};
|
||||
pub use sp_state_machine::ExecutionStrategy;
|
||||
pub use sc_service::client;
|
||||
pub use self::client_ext::{ClientExt, ClientBlockImportExt};
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::collections::HashMap;
|
||||
use sp_core::storage::ChildInfo;
|
||||
use sp_runtime::traits::{Block as BlockT, BlakeTwo256};
|
||||
use sc_client::LocalCallExecutor;
|
||||
use sc_service::client::{LocalCallExecutor, ClientConfig};
|
||||
|
||||
/// Test client light database backend.
|
||||
pub type LightBackend<Block> = sc_client::light::backend::Backend<
|
||||
pub type LightBackend<Block> = client::light::backend::Backend<
|
||||
sc_client_db::light::LightStorage<Block>,
|
||||
BlakeTwo256,
|
||||
>;
|
||||
@@ -175,15 +175,15 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
|
||||
self,
|
||||
executor: Executor,
|
||||
) -> (
|
||||
sc_client::Client<
|
||||
client::Client<
|
||||
Backend,
|
||||
Executor,
|
||||
Block,
|
||||
RuntimeApi,
|
||||
>,
|
||||
sc_client::LongestChain<Backend, Block>,
|
||||
sc_consensus::LongestChain<Backend, Block>,
|
||||
) where
|
||||
Executor: sc_client::CallExecutor<Block> + 'static,
|
||||
Executor: sc_client_api::CallExecutor<Block> + 'static,
|
||||
Backend: sc_client_api::backend::Backend<Block>,
|
||||
{
|
||||
let storage = {
|
||||
@@ -203,7 +203,7 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
|
||||
storage
|
||||
};
|
||||
|
||||
let client = sc_client::Client::new(
|
||||
let client = client::Client::new(
|
||||
self.backend.clone(),
|
||||
executor,
|
||||
&storage,
|
||||
@@ -214,10 +214,10 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
|
||||
self.keystore.clone(),
|
||||
),
|
||||
None,
|
||||
sc_client::ClientConfig::default(),
|
||||
ClientConfig::default(),
|
||||
).expect("Creates new client");
|
||||
|
||||
let longest_chain = sc_client::LongestChain::new(self.backend);
|
||||
let longest_chain = sc_consensus::LongestChain::new(self.backend);
|
||||
|
||||
(client, longest_chain)
|
||||
}
|
||||
@@ -225,7 +225,7 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
|
||||
|
||||
impl<Block: BlockT, E, Backend, G: GenesisInit> TestClientBuilder<
|
||||
Block,
|
||||
sc_client::LocalCallExecutor<Backend, NativeExecutor<E>>,
|
||||
client::LocalCallExecutor<Backend, NativeExecutor<E>>,
|
||||
Backend,
|
||||
G,
|
||||
> {
|
||||
@@ -234,13 +234,13 @@ impl<Block: BlockT, E, Backend, G: GenesisInit> TestClientBuilder<
|
||||
self,
|
||||
executor: I,
|
||||
) -> (
|
||||
sc_client::Client<
|
||||
client::Client<
|
||||
Backend,
|
||||
sc_client::LocalCallExecutor<Backend, NativeExecutor<E>>,
|
||||
client::LocalCallExecutor<Backend, NativeExecutor<E>>,
|
||||
Block,
|
||||
RuntimeApi
|
||||
>,
|
||||
sc_client::LongestChain<Backend, Block>,
|
||||
sc_consensus::LongestChain<Backend, Block>,
|
||||
) where
|
||||
I: Into<Option<NativeExecutor<E>>>,
|
||||
E: sc_executor::NativeExecutionDispatch + 'static,
|
||||
|
||||
@@ -17,12 +17,10 @@ sp-application-crypto = { version = "2.0.0-dev", default-features = false, path
|
||||
sp-consensus-aura = { version = "0.8.0-dev", default-features = false, path = "../../primitives/consensus/aura" }
|
||||
sp-consensus-babe = { version = "0.8.0-dev", default-features = false, path = "../../primitives/consensus/babe" }
|
||||
sp-block-builder = { version = "2.0.0-dev", default-features = false, path = "../../primitives/block-builder" }
|
||||
cfg-if = "0.1.10"
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] }
|
||||
frame-executive = { version = "2.0.0-dev", default-features = false, path = "../../frame/executive" }
|
||||
sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" }
|
||||
sp-keyring = { version = "2.0.0-dev", optional = true, path = "../../primitives/keyring" }
|
||||
log = { version = "0.4.8", optional = true }
|
||||
memory-db = { version = "0.20.0", default-features = false }
|
||||
sp-offchain = { path = "../../primitives/offchain", default-features = false, version = "2.0.0-dev"}
|
||||
sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" }
|
||||
@@ -31,7 +29,6 @@ sp-runtime-interface = { path = "../../primitives/runtime-interface", default-fe
|
||||
sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" }
|
||||
frame-support = { version = "2.0.0-dev", default-features = false, path = "../../frame/support" }
|
||||
sp-version = { version = "2.0.0-dev", default-features = false, path = "../../primitives/version" }
|
||||
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||
sp-session = { version = "2.0.0-dev", default-features = false, path = "../../primitives/session" }
|
||||
sp-api = { version = "2.0.0-dev", default-features = false, path = "../../primitives/api" }
|
||||
sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" }
|
||||
@@ -39,11 +36,16 @@ pallet-babe = { version = "2.0.0-dev", default-features = false, path = "../../f
|
||||
frame-system = { version = "2.0.0-dev", default-features = false, path = "../../frame/system" }
|
||||
frame-system-rpc-runtime-api = { version = "2.0.0-dev", default-features = false, path = "../../frame/system/rpc/runtime-api" }
|
||||
pallet-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../frame/timestamp" }
|
||||
sc-client = { version = "0.8.0-dev", optional = true, path = "../../client" }
|
||||
sp-trie = { version = "2.0.0-dev", default-features = false, path = "../../primitives/trie" }
|
||||
sp-transaction-pool = { version = "2.0.0-dev", default-features = false, path = "../../primitives/transaction-pool" }
|
||||
trie-db = { version = "0.20.1", default-features = false }
|
||||
parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" }
|
||||
|
||||
# 3rd party
|
||||
cfg-if = "0.1.10"
|
||||
log = { version = "0.4.8", optional = true }
|
||||
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "../../client/block-builder" }
|
||||
@@ -85,7 +87,7 @@ std = [
|
||||
"frame-system-rpc-runtime-api/std",
|
||||
"frame-system/std",
|
||||
"pallet-timestamp/std",
|
||||
"sc-client",
|
||||
"sc-service",
|
||||
"sp-trie/std",
|
||||
"sp-transaction-pool/std",
|
||||
"trie-db/std",
|
||||
|
||||
@@ -12,6 +12,7 @@ publish = false
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" }
|
||||
sc-block-builder = { version = "0.8.0-dev", path = "../../../client/block-builder" }
|
||||
substrate-test-client = { version = "2.0.0-dev", path = "../../client" }
|
||||
sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" }
|
||||
@@ -21,5 +22,6 @@ sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" }
|
||||
sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../../client/" }
|
||||
sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, path = "../../../client/service" }
|
||||
futures = "0.3.4"
|
||||
|
||||
@@ -26,7 +26,7 @@ use std::sync::Arc;
|
||||
use std::collections::HashMap;
|
||||
pub use substrate_test_client::*;
|
||||
pub use substrate_test_runtime as runtime;
|
||||
pub use sc_client::LongestChain;
|
||||
pub use sc_consensus::LongestChain;
|
||||
|
||||
pub use self::block_builder_ext::BlockBuilderExt;
|
||||
|
||||
@@ -34,7 +34,7 @@ use sp_core::{sr25519, ChangesTrieConfiguration};
|
||||
use sp_core::storage::{ChildInfo, Storage, StorageChild};
|
||||
use substrate_test_runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, NumberFor, HashFor};
|
||||
use sc_client::{
|
||||
use sc_service::client::{
|
||||
light::fetcher::{
|
||||
Fetcher,
|
||||
RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest,
|
||||
@@ -68,7 +68,7 @@ sc_executor::native_executor_instance! {
|
||||
pub type Backend = substrate_test_client::Backend<substrate_test_runtime::Block>;
|
||||
|
||||
/// Test client executor.
|
||||
pub type Executor = sc_client::LocalCallExecutor<
|
||||
pub type Executor = client::LocalCallExecutor<
|
||||
Backend,
|
||||
NativeExecutor<LocalExecutor>,
|
||||
>;
|
||||
@@ -77,10 +77,10 @@ pub type Executor = sc_client::LocalCallExecutor<
|
||||
pub type LightBackend = substrate_test_client::LightBackend<substrate_test_runtime::Block>;
|
||||
|
||||
/// Test client light executor.
|
||||
pub type LightExecutor = sc_client::light::call_executor::GenesisCallExecutor<
|
||||
pub type LightExecutor = client::light::call_executor::GenesisCallExecutor<
|
||||
LightBackend,
|
||||
sc_client::LocalCallExecutor<
|
||||
sc_client::light::backend::Backend<
|
||||
client::LocalCallExecutor<
|
||||
client::light::backend::Backend<
|
||||
sc_client_db::light::LightStorage<substrate_test_runtime::Block>,
|
||||
HashFor<substrate_test_runtime::Block>
|
||||
>,
|
||||
@@ -133,7 +133,7 @@ impl substrate_test_client::GenesisInit for GenesisParameters {
|
||||
let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||
storage.top.clone().into_iter().chain(child_roots).collect()
|
||||
);
|
||||
let block: runtime::Block = sc_client::genesis::construct_genesis_block(state_root);
|
||||
let block: runtime::Block = client::genesis::construct_genesis_block(state_root);
|
||||
storage.top.extend(additional_storage_with_genesis(&block));
|
||||
|
||||
storage
|
||||
@@ -149,9 +149,9 @@ pub type TestClientBuilder<E, B> = substrate_test_client::TestClientBuilder<
|
||||
>;
|
||||
|
||||
/// Test client type with `LocalExecutor` and generic Backend.
|
||||
pub type Client<B> = sc_client::Client<
|
||||
pub type Client<B> = client::Client<
|
||||
B,
|
||||
sc_client::LocalCallExecutor<B, sc_executor::NativeExecutor<LocalExecutor>>,
|
||||
client::LocalCallExecutor<B, sc_executor::NativeExecutor<LocalExecutor>>,
|
||||
substrate_test_runtime::Block,
|
||||
substrate_test_runtime::RuntimeApi,
|
||||
>;
|
||||
@@ -230,14 +230,14 @@ pub trait TestClientBuilderExt<B>: Sized {
|
||||
}
|
||||
|
||||
/// Build the test client and longest chain selector.
|
||||
fn build_with_longest_chain(self) -> (Client<B>, sc_client::LongestChain<B, substrate_test_runtime::Block>);
|
||||
fn build_with_longest_chain(self) -> (Client<B>, sc_consensus::LongestChain<B, substrate_test_runtime::Block>);
|
||||
|
||||
/// Build the test client and the backend.
|
||||
fn build_with_backend(self) -> (Client<B>, Arc<B>);
|
||||
}
|
||||
|
||||
impl<B> TestClientBuilderExt<B> for TestClientBuilder<
|
||||
sc_client::LocalCallExecutor<B, sc_executor::NativeExecutor<LocalExecutor>>,
|
||||
client::LocalCallExecutor<B, sc_executor::NativeExecutor<LocalExecutor>>,
|
||||
B
|
||||
> where
|
||||
B: sc_client_api::backend::Backend<substrate_test_runtime::Block> + 'static,
|
||||
@@ -249,7 +249,7 @@ impl<B> TestClientBuilderExt<B> for TestClientBuilder<
|
||||
Self::genesis_init_mut(self)
|
||||
}
|
||||
|
||||
fn build_with_longest_chain(self) -> (Client<B>, sc_client::LongestChain<B, substrate_test_runtime::Block>) {
|
||||
fn build_with_longest_chain(self) -> (Client<B>, sc_consensus::LongestChain<B, substrate_test_runtime::Block>) {
|
||||
self.build_with_native_executor(None)
|
||||
}
|
||||
|
||||
@@ -344,15 +344,15 @@ pub fn new() -> Client<Backend> {
|
||||
|
||||
/// Creates new light client instance used for tests.
|
||||
pub fn new_light() -> (
|
||||
sc_client::Client<LightBackend, LightExecutor, substrate_test_runtime::Block, substrate_test_runtime::RuntimeApi>,
|
||||
client::Client<LightBackend, LightExecutor, substrate_test_runtime::Block, substrate_test_runtime::RuntimeApi>,
|
||||
Arc<LightBackend>,
|
||||
) {
|
||||
|
||||
let storage = sc_client_db::light::LightStorage::new_test();
|
||||
let blockchain = Arc::new(sc_client::light::blockchain::Blockchain::new(storage));
|
||||
let blockchain = Arc::new(client::light::blockchain::Blockchain::new(storage));
|
||||
let backend = Arc::new(LightBackend::new(blockchain.clone()));
|
||||
let executor = new_native_executor();
|
||||
let local_call_executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, sp_core::tasks::executor(), Default::default());
|
||||
let local_call_executor = client::LocalCallExecutor::new(backend.clone(), executor, sp_core::tasks::executor(), Default::default());
|
||||
let call_executor = LightExecutor::new(
|
||||
backend.clone(),
|
||||
local_call_executor,
|
||||
|
||||
@@ -26,7 +26,7 @@ use crate::{
|
||||
};
|
||||
use sc_client_api::backend;
|
||||
use sc_client_api::blockchain::{Backend as BlockChainBackendT, HeaderBackend};
|
||||
use substrate_test_client::sp_consensus::BlockOrigin;
|
||||
use sp_consensus::BlockOrigin;
|
||||
use substrate_test_runtime::{self, Transfer};
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_runtime::traits::{Block as BlockT, HashFor};
|
||||
|
||||
@@ -23,6 +23,7 @@ use codec::{Encode, KeyedVec, Joiner};
|
||||
use sp_core::{ChangesTrieConfiguration, map};
|
||||
use sp_core::storage::{well_known_keys, Storage};
|
||||
use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
|
||||
use sc_service::client::genesis;
|
||||
|
||||
/// Configuration of a general Substrate test genesis block.
|
||||
pub struct GenesisConfig {
|
||||
@@ -96,7 +97,7 @@ pub fn insert_genesis_block(
|
||||
let state_root = <<<crate::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||
storage.top.clone().into_iter().collect()
|
||||
);
|
||||
let block: crate::Block = sc_client::genesis::construct_genesis_block(state_root);
|
||||
let block: crate::Block = genesis::construct_genesis_block(state_root);
|
||||
let genesis_hash = block.header.hash();
|
||||
storage.top.extend(additional_storage_with_genesis(&block));
|
||||
genesis_hash
|
||||
|
||||
@@ -16,7 +16,6 @@ frame-benchmarking = { version = "2.0.0-dev", path = "../../../frame/benchmarkin
|
||||
sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" }
|
||||
sc-service = { version = "0.8.0-dev", default-features = false, path = "../../../client/service" }
|
||||
sc-cli = { version = "0.8.0-dev", path = "../../../client/cli" }
|
||||
sc-client = { version = "0.8.0-dev", path = "../../../client" }
|
||||
sc-client-db = { version = "0.8.0-dev", path = "../../../client/db" }
|
||||
sc-executor = { version = "0.8.0-dev", path = "../../../client/executor" }
|
||||
sp-externalities = { version = "0.8.0-dev", path = "../../../primitives/externalities" }
|
||||
|
||||
@@ -18,9 +18,9 @@ use crate::BenchmarkCmd;
|
||||
use codec::{Decode, Encode};
|
||||
use frame_benchmarking::{Analysis, BenchmarkBatch};
|
||||
use sc_cli::{SharedParams, CliConfiguration, ExecutionStrategy, Result};
|
||||
use sc_client::StateMachine;
|
||||
use sc_client_db::BenchmarkingState;
|
||||
use sc_executor::NativeExecutor;
|
||||
use sp_state_machine::StateMachine;
|
||||
use sp_externalities::Extensions;
|
||||
use sc_service::{Configuration, NativeExecutionDispatch};
|
||||
use sp_runtime::{
|
||||
|
||||
@@ -12,7 +12,7 @@ description = "FRAME's system exposed over Substrate RPC"
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
sc-client = { version = "0.8.0-dev", path = "../../../../client/" }
|
||||
sc-client-api = { version = "2.0.0-dev", path = "../../../../client/api" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0" }
|
||||
futures = "0.3.4"
|
||||
jsonrpc-core = "14.0.3"
|
||||
|
||||
@@ -19,10 +19,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use codec::{self, Codec, Decode, Encode};
|
||||
use sc_client::{
|
||||
light::blockchain::{future_header, RemoteBlockchain},
|
||||
light::fetcher::{Fetcher, RemoteCallRequest},
|
||||
};
|
||||
use sc_client_api::light::{future_header, RemoteBlockchain, Fetcher, RemoteCallRequest};
|
||||
use jsonrpc_core::{
|
||||
Error, ErrorCode,
|
||||
futures::future::{result, Future},
|
||||
|
||||
Reference in New Issue
Block a user