mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 23:31:07 +00:00
Make runtime api calls native when possible (#1302)
* Add simple benchmark for the runtime api * Make the executor support native calls * Some documentation * Hide behind `feature = "std"` * Rework the native calls * Make all tests compile again * Make every parameter using the Block serialized/deserialized in the native call * Forward `UnwindSafe` requirement * Remove debug stuff * Add some documentation * Fixes warnings * Fixes errors after master rebase * Fixes compilation after master rebase * Fixes compilation after rebase
This commit is contained in:
Generated
+200
@@ -303,6 +303,11 @@ name = "cast"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.28"
|
||||
@@ -424,6 +429,29 @@ dependencies = [
|
||||
"simplelog 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"criterion-plot 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"criterion-stats 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools-num 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.1.3"
|
||||
@@ -434,6 +462,18 @@ dependencies = [
|
||||
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-stats"
|
||||
version = "0.1.3"
|
||||
@@ -446,6 +486,18 @@ dependencies = [
|
||||
"thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-stats"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.6.0"
|
||||
@@ -561,6 +613,23 @@ dependencies = [
|
||||
"subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv-core"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.1.1"
|
||||
@@ -913,6 +982,21 @@ dependencies = [
|
||||
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "handlebars"
|
||||
version = "0.32.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash-db"
|
||||
version = "0.9.0"
|
||||
@@ -1115,6 +1199,22 @@ dependencies = [
|
||||
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools-num"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.3"
|
||||
@@ -2200,6 +2300,21 @@ name = "percent-encoding"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.14"
|
||||
@@ -2289,6 +2404,11 @@ name = "quick-error"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.5.2"
|
||||
@@ -2608,6 +2728,14 @@ name = "safemem"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.14"
|
||||
@@ -2742,6 +2870,16 @@ dependencies = [
|
||||
"time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simplelog"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.1"
|
||||
@@ -2796,6 +2934,7 @@ name = "sr-api-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"criterion 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 0.1.0",
|
||||
@@ -3951,6 +4090,16 @@ name = "subtle"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.13.11"
|
||||
@@ -3981,6 +4130,14 @@ dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.10.1"
|
||||
@@ -4044,6 +4201,15 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.0.4"
|
||||
@@ -4445,6 +4611,11 @@ name = "unicode-width"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
@@ -4539,6 +4710,16 @@ dependencies = [
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.0.6"
|
||||
@@ -4743,6 +4924,7 @@ dependencies = [
|
||||
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
|
||||
"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
|
||||
"checksum cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "011941fb53da1a8ac3e4132a1becc367c44fe13f630769f3143d8c66c91c6cb6"
|
||||
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
|
||||
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
|
||||
"checksum cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fc0086be9ca82f7fc89fc873435531cb898b86e850005850de1f820e2db6e9b"
|
||||
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
||||
@@ -4756,8 +4938,11 @@ dependencies = [
|
||||
"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
|
||||
"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
|
||||
"checksum criterion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f58b0200bf321214bdda8c797cf0071bcc638171c40ec198c3f652a4edaacde3"
|
||||
"checksum criterion 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c47d2b548c5647e1a436dc0cb78d4ebf51b6bf7ab101ed76662828bdd4d3a24a"
|
||||
"checksum criterion-plot 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "885431f7865f9d4956b466126674e5ea40a0f193d42157e56630c356c5501957"
|
||||
"checksum criterion-plot 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5f81689739e463ece7a6b62c6ec63bdab5c4e28fe05ff451769e87d1511411"
|
||||
"checksum criterion-stats 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c71521cb4c7b7eac76b540e75447fb0172c4234d6333729001b886aaa21d6da4"
|
||||
"checksum criterion-stats 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ff43cac80562f91ead0b617c1be74edf350adfaa195809d355de98dfc8f9237d"
|
||||
"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94"
|
||||
"checksum crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "137bc235f622ffaa0428e3854e24acb53291fc0b3ff6fb2cb75a8be6fb02f06b"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
@@ -4770,6 +4955,8 @@ dependencies = [
|
||||
"checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2"
|
||||
"checksum crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971"
|
||||
"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
|
||||
"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04"
|
||||
"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65"
|
||||
"checksum ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4b669fcb8e20124db86dbd9b01e74ec0e9e420e65381311ce5249864fc7ff0c0"
|
||||
"checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e"
|
||||
"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f"
|
||||
@@ -4812,6 +4999,7 @@ dependencies = [
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865"
|
||||
"checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0"
|
||||
"checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd"
|
||||
"checksum hash-db 0.9.0 (git+https://github.com/paritytech/trie)" = "<none>"
|
||||
"checksum hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)" = "<none>"
|
||||
"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
|
||||
@@ -4835,6 +5023,8 @@ dependencies = [
|
||||
"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc"
|
||||
"checksum itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c4a9b56eb56058f43dc66e58f40a214b2ccbc9f3df51861b63d51dec7b65bc3f"
|
||||
"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc"
|
||||
"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
|
||||
"checksum itertools-num 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a872a22f9e6f7521ca557660adb96dd830e54f0f490fa115bb55dd69d38b27e7"
|
||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||
"checksum jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
|
||||
"checksum jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
|
||||
@@ -4927,6 +5117,8 @@ dependencies = [
|
||||
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
|
||||
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
|
||||
"checksum pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3294f437119209b084c797604295f40227cffa35c57220b1e99a6ff3bf8ee4"
|
||||
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
||||
"checksum pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28ea5118e2f41bfbc974b28d88c07621befd1fa5d6ec23549be96302a1a59dd2"
|
||||
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
|
||||
@@ -4939,6 +5131,7 @@ dependencies = [
|
||||
"checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4"
|
||||
"checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d"
|
||||
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
|
||||
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
|
||||
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
|
||||
@@ -4976,6 +5169,7 @@ dependencies = [
|
||||
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||
"checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347"
|
||||
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
|
||||
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
|
||||
"checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56"
|
||||
"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
@@ -4992,6 +5186,7 @@ dependencies = [
|
||||
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
|
||||
"checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c"
|
||||
"checksum simplelog 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "24b615b1a3cc51ffa565d9a1d0cfcc49fe7d64737ada84eca284cddb0292d125"
|
||||
"checksum simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e95345f185d5adeb8ec93459d2dc99654e294cc6ccf5b75414d8ea262de9a13"
|
||||
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
|
||||
"checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e"
|
||||
"checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f"
|
||||
@@ -5011,9 +5206,11 @@ dependencies = [
|
||||
"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04"
|
||||
"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
|
||||
"checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b"
|
||||
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
||||
"checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||
"checksum sysinfo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c747a1fbe091faa7bf76c19f40099f9f12495384c811485d81cf3d60c0eae62"
|
||||
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
|
||||
@@ -5021,6 +5218,7 @@ dependencies = [
|
||||
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||
"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
|
||||
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
|
||||
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
|
||||
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
|
||||
@@ -5062,6 +5260,7 @@ dependencies = [
|
||||
"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
|
||||
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
|
||||
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8abc4b7d8158bdfbbaaccc35331ed3c30c2673e99000d7ae665a2eb6576f4"
|
||||
@@ -5075,6 +5274,7 @@ dependencies = [
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add"
|
||||
"checksum wabt-sys 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "462336bb61096e64761730e0dea1bc8b777bd4e3689c7e813c81f1cfdf4e8a51"
|
||||
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
|
||||
"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
|
||||
"checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d"
|
||||
"checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703"
|
||||
|
||||
@@ -22,8 +22,10 @@ use std::sync::Arc;
|
||||
use std::time;
|
||||
use std;
|
||||
|
||||
use client::{self, error, Client as SubstrateClient, CallExecutor};
|
||||
use client::{block_builder::api::BlockBuilder as BlockBuilderApi, runtime_api::Core};
|
||||
use client::{
|
||||
self, error, Client as SubstrateClient, CallExecutor,
|
||||
block_builder::api::BlockBuilder as BlockBuilderApi, runtime_api::{Core, ApiExt}
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
use consensus_common::{self, evaluation};
|
||||
use primitives::{H256, Blake2Hasher};
|
||||
@@ -68,7 +70,9 @@ where
|
||||
B: client::backend::Backend<Block, Blake2Hasher> + 'static,
|
||||
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
|
||||
Block: BlockT<Hash=H256>,
|
||||
RA: BlockBuilderApi<Block, BasicInherentData>,
|
||||
RA: Send + Sync + 'static,
|
||||
SubstrateClient<B, E, Block, RA> : ProvideRuntimeApi,
|
||||
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api: BlockBuilderApi<Block, BasicInherentData>,
|
||||
{
|
||||
fn push_extrinsic(&mut self, extrinsic: <Block as BlockT>::Extrinsic) -> Result<(), error::Error> {
|
||||
client::block_builder::BlockBuilder::push(self, extrinsic).map_err(Into::into)
|
||||
@@ -79,7 +83,9 @@ impl<B, E, Block, RA> AuthoringApi for SubstrateClient<B, E, Block, RA> where
|
||||
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
|
||||
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
|
||||
Block: BlockT<Hash=H256>,
|
||||
RA: BlockBuilderApi<Block, BasicInherentData>,
|
||||
RA: Send + Sync + 'static,
|
||||
SubstrateClient<B, E, Block, RA> : ProvideRuntimeApi,
|
||||
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api: BlockBuilderApi<Block, BasicInherentData>,
|
||||
{
|
||||
type Block = Block;
|
||||
type Error = client::error::Error;
|
||||
@@ -94,7 +100,7 @@ impl<B, E, Block, RA> AuthoringApi for SubstrateClient<B, E, Block, RA> where
|
||||
|
||||
let runtime_api = self.runtime_api();
|
||||
if runtime_api.has_api::<BlockBuilderApi<Block, BasicInherentData>>(at)? {
|
||||
runtime_api.inherent_extrinsics(at, &inherent_data)?
|
||||
runtime_api.inherent_extrinsics(at, inherent_data)?
|
||||
.into_iter().try_for_each(|i| block_builder.push(i))?;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,12 +84,12 @@ where
|
||||
/// the error. Otherwise, it will return a mutable reference to self (in order to chain).
|
||||
pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> error::Result<()> {
|
||||
use crate::runtime_api::ApiExt;
|
||||
|
||||
|
||||
let block_id = &self.block_id;
|
||||
let extrinsics = &mut self.extrinsics;
|
||||
|
||||
|
||||
self.api.map_api_result(|api| {
|
||||
match api.apply_extrinsic(block_id, &xt)? {
|
||||
match api.apply_extrinsic(block_id, xt.clone())? {
|
||||
Ok(ApplyOutcome::Success) | Ok(ApplyOutcome::Fail) => {
|
||||
extrinsics.push(xt);
|
||||
Ok(())
|
||||
|
||||
@@ -14,17 +14,17 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::cmp::Ord;
|
||||
use codec::Encode;
|
||||
use std::{sync::Arc, cmp::Ord, panic::UnwindSafe};
|
||||
use codec::{Encode, Decode};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::Block as BlockT;
|
||||
use state_machine::{self, OverlayedChanges, Ext,
|
||||
CodeExecutor, ExecutionManager, native_when_possible};
|
||||
use state_machine::{
|
||||
self, OverlayedChanges, Ext, CodeExecutor, ExecutionManager, native_when_possible
|
||||
};
|
||||
use executor::{RuntimeVersion, RuntimeInfo, NativeVersion};
|
||||
use hash_db::Hasher;
|
||||
use trie::MemoryDB;
|
||||
use primitives::{H256, Blake2Hasher};
|
||||
use primitives::{H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue};
|
||||
|
||||
use crate::backend;
|
||||
use crate::error;
|
||||
@@ -56,7 +56,12 @@ where
|
||||
/// of the execution context.
|
||||
fn contextual_call<
|
||||
PB: Fn() -> error::Result<B::Header>,
|
||||
EM: Fn(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>,
|
||||
EM: Fn(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
at: &BlockId<B>,
|
||||
@@ -66,7 +71,8 @@ where
|
||||
initialised_block: &mut Option<BlockId<B>>,
|
||||
prepare_environment_block: PB,
|
||||
manager: ExecutionManager<EM>,
|
||||
) -> error::Result<Vec<u8>> where ExecutionManager<EM>: Clone;
|
||||
native_call: Option<NC>,
|
||||
) -> error::Result<NativeOrEncoded<R>> where ExecutionManager<EM>: Clone;
|
||||
|
||||
/// Extract RuntimeVersion of given block
|
||||
///
|
||||
@@ -78,14 +84,20 @@ where
|
||||
/// No changes are made.
|
||||
fn call_at_state<
|
||||
S: state_machine::Backend<H>,
|
||||
F: FnOnce(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>,
|
||||
F: FnOnce(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
>(&self,
|
||||
state: &S,
|
||||
overlay: &mut OverlayedChanges,
|
||||
method: &str,
|
||||
call_data: &[u8],
|
||||
manager: ExecutionManager<F>
|
||||
) -> Result<(Vec<u8>, S::Transaction, Option<MemoryDB<H>>), error::Error>;
|
||||
manager: ExecutionManager<F>,
|
||||
native_call: Option<NC>,
|
||||
) -> Result<(NativeOrEncoded<R>, S::Transaction, Option<MemoryDB<H>>), error::Error>;
|
||||
|
||||
/// Execute a call to a contract on top of given state, gathering execution proof.
|
||||
///
|
||||
@@ -155,7 +167,9 @@ where
|
||||
) -> error::Result<Vec<u8>> {
|
||||
let mut changes = OverlayedChanges::default();
|
||||
let state = self.backend.state_at(*id)?;
|
||||
let return_data = state_machine::execute_using_consensus_failure_handler(
|
||||
let return_data = state_machine::execute_using_consensus_failure_handler::<
|
||||
_, _, _, _, _, _, fn() -> NeverNativeValue
|
||||
>(
|
||||
&state,
|
||||
self.backend.changes_trie_storage(),
|
||||
&mut changes,
|
||||
@@ -164,15 +178,21 @@ where
|
||||
call_data,
|
||||
native_when_possible(),
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.map(|(result, _, _)| result)?;
|
||||
self.backend.destroy_state(state)?;
|
||||
Ok(return_data)
|
||||
Ok(return_data.into_encoded())
|
||||
}
|
||||
|
||||
fn contextual_call<
|
||||
PB: Fn() -> error::Result<Block::Header>,
|
||||
EM: Fn(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>,
|
||||
EM: Fn(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
@@ -182,12 +202,15 @@ where
|
||||
initialised_block: &mut Option<BlockId<Block>>,
|
||||
prepare_environment_block: PB,
|
||||
manager: ExecutionManager<EM>,
|
||||
) -> Result<Vec<u8>, error::Error> where ExecutionManager<EM>: Clone {
|
||||
native_call: Option<NC>,
|
||||
) -> Result<NativeOrEncoded<R>, error::Error> where ExecutionManager<EM>: Clone {
|
||||
let state = self.backend.state_at(*at)?;
|
||||
//TODO: Find a better way to prevent double block initialization
|
||||
if method != "Core_initialise_block" && initialised_block.map(|id| id != *at).unwrap_or(true) {
|
||||
let header = prepare_environment_block()?;
|
||||
state_machine::execute_using_consensus_failure_handler(
|
||||
state_machine::execute_using_consensus_failure_handler::<
|
||||
_, _, _, _, _, R, fn() -> R,
|
||||
>(
|
||||
&state,
|
||||
self.backend.changes_trie_storage(),
|
||||
changes,
|
||||
@@ -196,6 +219,7 @@ where
|
||||
&header.encode(),
|
||||
manager.clone(),
|
||||
false,
|
||||
None,
|
||||
)?;
|
||||
*initialised_block = Some(*at);
|
||||
}
|
||||
@@ -209,8 +233,8 @@ where
|
||||
call_data,
|
||||
manager,
|
||||
false,
|
||||
)
|
||||
.map(|(result, _, _)| result)?;
|
||||
native_call,
|
||||
).map(|(result, _, _)| result)?;
|
||||
|
||||
self.backend.destroy_state(state)?;
|
||||
Ok(result)
|
||||
@@ -226,14 +250,20 @@ where
|
||||
|
||||
fn call_at_state<
|
||||
S: state_machine::Backend<Blake2Hasher>,
|
||||
F: FnOnce(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>,
|
||||
F: FnOnce(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
>(&self,
|
||||
state: &S,
|
||||
changes: &mut OverlayedChanges,
|
||||
method: &str,
|
||||
call_data: &[u8],
|
||||
manager: ExecutionManager<F>,
|
||||
) -> error::Result<(Vec<u8>, S::Transaction, Option<MemoryDB<Blake2Hasher>>)> {
|
||||
native_call: Option<NC>,
|
||||
) -> error::Result<(NativeOrEncoded<R>, S::Transaction, Option<MemoryDB<Blake2Hasher>>)> {
|
||||
state_machine::execute_using_consensus_failure_handler(
|
||||
state,
|
||||
self.backend.changes_trie_storage(),
|
||||
@@ -243,6 +273,7 @@ where
|
||||
call_data,
|
||||
manager,
|
||||
true,
|
||||
native_call,
|
||||
)
|
||||
.map(|(result, storage_tx, changes_tx)| (
|
||||
result,
|
||||
|
||||
@@ -16,25 +16,29 @@
|
||||
|
||||
//! Substrate Client
|
||||
|
||||
use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc};
|
||||
use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc, panic::UnwindSafe};
|
||||
use crate::error::Error;
|
||||
use futures::sync::mpsc;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use primitives::NativeOrEncoded;
|
||||
use runtime_primitives::{
|
||||
Justification,
|
||||
generic::{BlockId, SignedBlock},
|
||||
};
|
||||
use consensus::{Error as ConsensusError, ErrorKind as ConsensusErrorKind, ImportBlock, ImportResult, BlockOrigin, ForkChoiceStrategy};
|
||||
use consensus::{
|
||||
Error as ConsensusError, ErrorKind as ConsensusErrorKind, ImportBlock, ImportResult,
|
||||
BlockOrigin, ForkChoiceStrategy
|
||||
};
|
||||
use runtime_primitives::traits::{
|
||||
Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash,
|
||||
ApiRef, ProvideRuntimeApi, Digest, DigestItem, AuthorityIdFor
|
||||
};
|
||||
use runtime_primitives::BuildStorage;
|
||||
use crate::runtime_api::{Core as CoreAPI, CallRuntimeAt, ConstructRuntimeApi};
|
||||
use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash};
|
||||
use crate::runtime_api::{CallRuntimeAt, ConstructRuntimeApi};
|
||||
use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue};
|
||||
use primitives::storage::{StorageKey, StorageData};
|
||||
use primitives::storage::well_known_keys;
|
||||
use codec::Decode;
|
||||
use codec::{Encode, Decode};
|
||||
use state_machine::{
|
||||
DBValue, Backend as StateBackend, CodeExecutor, ChangesTrieAnchorBlockId,
|
||||
ExecutionStrategy, ExecutionManager, prove_read,
|
||||
@@ -557,7 +561,9 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
&self
|
||||
) -> error::Result<block_builder::BlockBuilder<Block, InherentData, Self>> where
|
||||
E: Clone + Send + Sync,
|
||||
RA: BlockBuilderAPI<Block, InherentData>
|
||||
RA: Send + Sync,
|
||||
Self: ProvideRuntimeApi,
|
||||
<Self as ProvideRuntimeApi>::Api: BlockBuilderAPI<Block, InherentData>
|
||||
{
|
||||
block_builder::BlockBuilder::new(self)
|
||||
}
|
||||
@@ -567,7 +573,9 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
&self, parent: &BlockId<Block>
|
||||
) -> error::Result<block_builder::BlockBuilder<Block, InherentData, Self>> where
|
||||
E: Clone + Send + Sync,
|
||||
RA: BlockBuilderAPI<Block, InherentData>
|
||||
RA: Send + Sync,
|
||||
Self: ProvideRuntimeApi,
|
||||
<Self as ProvideRuntimeApi>::Api: BlockBuilderAPI<Block, InherentData>
|
||||
{
|
||||
block_builder::BlockBuilder::at_block(parent, &self)
|
||||
}
|
||||
@@ -615,7 +623,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
let (storage_update, changes_update, storage_changes) = match transaction.state()? {
|
||||
Some(transaction_state) => {
|
||||
let mut overlay = Default::default();
|
||||
let r = self.executor.call_at_state(
|
||||
let r = self.executor.call_at_state::<_, _, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
transaction_state,
|
||||
&mut overlay,
|
||||
"Core_execute_block",
|
||||
@@ -638,6 +646,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
wasm_result
|
||||
}),
|
||||
},
|
||||
None,
|
||||
);
|
||||
let (_, storage_update, changes_update) = r?;
|
||||
overlay.commit_prospective();
|
||||
@@ -1017,30 +1026,29 @@ impl<B, E, Block, RA> ProvideRuntimeApi for Client<B, E, Block, RA> where
|
||||
B: backend::Backend<Block, Blake2Hasher>,
|
||||
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync,
|
||||
Block: BlockT<Hash=H256>,
|
||||
RA: CoreAPI<Block>
|
||||
RA: ConstructRuntimeApi<Block, Self>
|
||||
{
|
||||
type Api = RA;
|
||||
type Api = <RA as ConstructRuntimeApi<Block, Self>>::RuntimeApi;
|
||||
|
||||
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
|
||||
Self::Api::construct_runtime_api(self)
|
||||
RA::construct_runtime_api(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E, Block, RA> CallRuntimeAt<Block> for Client<B, E, Block, RA> where
|
||||
B: backend::Backend<Block, Blake2Hasher>,
|
||||
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync,
|
||||
Block: BlockT<Hash=H256>,
|
||||
RA: CoreAPI<Block>, // not strictly necessary at the moment
|
||||
// but we want to bound to make sure the API is actually available.
|
||||
Block: BlockT<Hash=H256>
|
||||
{
|
||||
fn call_api_at(
|
||||
fn call_api_at<R: Encode + Decode + PartialEq, NC: FnOnce() -> R + UnwindSafe>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
function: &'static str,
|
||||
args: Vec<u8>,
|
||||
changes: &mut OverlayedChanges,
|
||||
initialised_block: &mut Option<BlockId<Block>>,
|
||||
) -> error::Result<Vec<u8>> {
|
||||
native_call: Option<NC>,
|
||||
) -> error::Result<NativeOrEncoded<R>> {
|
||||
let execution_manager = match self.api_execution_strategy {
|
||||
ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible,
|
||||
ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm,
|
||||
@@ -1053,8 +1061,16 @@ impl<B, E, Block, RA> CallRuntimeAt<Block> for Client<B, E, Block, RA> where
|
||||
}),
|
||||
};
|
||||
|
||||
self.executor.contextual_call(at, function, &args, changes, initialised_block,
|
||||
|| self.prepare_environment_block(at), execution_manager)
|
||||
self.executor.contextual_call(
|
||||
at,
|
||||
function,
|
||||
&args,
|
||||
changes,
|
||||
initialised_block,
|
||||
|| self.prepare_environment_block(at),
|
||||
execution_manager,
|
||||
native_call,
|
||||
)
|
||||
}
|
||||
|
||||
fn runtime_version_at(&self, at: &BlockId<Block>) -> error::Result<RuntimeVersion> {
|
||||
@@ -1268,7 +1284,7 @@ pub(crate) mod tests {
|
||||
use consensus::BlockOrigin;
|
||||
use test_client::client::{backend::Backend as TestBackend, runtime_api::ApiExt};
|
||||
use test_client::BlockBuilderExt;
|
||||
use test_client::runtime::{self, Block, Transfer, RuntimeApi, test_api::TestAPI};
|
||||
use test_client::runtime::{self, Block, Transfer, RuntimeApi, TestAPI};
|
||||
|
||||
/// Returns tuple, consisting of:
|
||||
/// 1) test client pre-filled with blocks changing balances;
|
||||
@@ -1350,14 +1366,14 @@ pub(crate) mod tests {
|
||||
assert_eq!(
|
||||
client.runtime_api().balance_of(
|
||||
&BlockId::Number(client.info().unwrap().chain.best_number),
|
||||
&Keyring::Alice.to_raw_public().into()
|
||||
Keyring::Alice.to_raw_public().into()
|
||||
).unwrap(),
|
||||
1000
|
||||
);
|
||||
assert_eq!(
|
||||
client.runtime_api().balance_of(
|
||||
&BlockId::Number(client.info().unwrap().chain.best_number),
|
||||
&Keyring::Ferdie.to_raw_public().into()
|
||||
Keyring::Ferdie.to_raw_public().into()
|
||||
).unwrap(),
|
||||
0
|
||||
);
|
||||
@@ -1417,14 +1433,14 @@ pub(crate) mod tests {
|
||||
assert_eq!(
|
||||
client.runtime_api().balance_of(
|
||||
&BlockId::Number(client.info().unwrap().chain.best_number),
|
||||
&Keyring::Alice.to_raw_public().into()
|
||||
Keyring::Alice.to_raw_public().into()
|
||||
).unwrap(),
|
||||
958
|
||||
);
|
||||
assert_eq!(
|
||||
client.runtime_api().balance_of(
|
||||
&BlockId::Number(client.info().unwrap().chain.best_number),
|
||||
&Keyring::Ferdie.to_raw_public().into()
|
||||
Keyring::Ferdie.to_raw_public().into()
|
||||
).unwrap(),
|
||||
42
|
||||
);
|
||||
|
||||
@@ -17,13 +17,11 @@
|
||||
//! Light client call exector. Executes methods on remote full nodes, fetching
|
||||
//! execution proof and checking it locally.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use std::{collections::HashSet, marker::PhantomData, sync::Arc};
|
||||
use futures::{IntoFuture, Future};
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
use primitives::{H256, Blake2Hasher, convert_hash};
|
||||
use primitives::{H256, Blake2Hasher, convert_hash, NativeOrEncoded};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT};
|
||||
use state_machine::{self, Backend as StateBackend, CodeExecutor, OverlayedChanges,
|
||||
@@ -88,7 +86,12 @@ where
|
||||
|
||||
fn contextual_call<
|
||||
PB: Fn() -> ClientResult<Block::Header>,
|
||||
EM: Fn(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>,
|
||||
EM: Fn(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC,
|
||||
>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
@@ -98,13 +101,14 @@ where
|
||||
initialised_block: &mut Option<BlockId<Block>>,
|
||||
_prepare_environment_block: PB,
|
||||
_manager: ExecutionManager<EM>,
|
||||
) -> ClientResult<Vec<u8>> where ExecutionManager<EM>: Clone {
|
||||
_native_call: Option<NC>,
|
||||
) -> ClientResult<NativeOrEncoded<R>> where ExecutionManager<EM>: Clone {
|
||||
// it is only possible to execute contextual call if changes are empty
|
||||
if !changes.is_empty() || initialised_block.is_some() {
|
||||
return Err(ClientErrorKind::NotAvailableOnLightClient.into());
|
||||
}
|
||||
|
||||
self.call(at, method, call_data)
|
||||
self.call(at, method, call_data).map(NativeOrEncoded::Encoded)
|
||||
}
|
||||
|
||||
fn runtime_version(&self, id: &BlockId<Block>) -> ClientResult<RuntimeVersion> {
|
||||
@@ -115,14 +119,20 @@ where
|
||||
|
||||
fn call_at_state<
|
||||
S: StateBackend<H>,
|
||||
FF: FnOnce(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>
|
||||
FF: FnOnce(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R,
|
||||
>(&self,
|
||||
_state: &S,
|
||||
_changes: &mut OverlayedChanges,
|
||||
_method: &str,
|
||||
_call_data: &[u8],
|
||||
_m: ExecutionManager<FF>
|
||||
) -> ClientResult<(Vec<u8>, S::Transaction, Option<MemoryDB<H>>)> {
|
||||
_m: ExecutionManager<FF>,
|
||||
_native_call: Option<NC>,
|
||||
) -> ClientResult<(NativeOrEncoded<R>, S::Transaction, Option<MemoryDB<H>>)> {
|
||||
Err(ClientErrorKind::NotAvailableOnLightClient.into())
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#[cfg(feature = "std")]
|
||||
pub use state_machine::OverlayedChanges;
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "std")]
|
||||
pub use primitives::NativeOrEncoded;
|
||||
#[doc(hidden)]
|
||||
pub use runtime_primitives::{
|
||||
traits::{AuthorityIdFor, Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, ApiRef, RuntimeApiInfo},
|
||||
generic::BlockId, transaction_validity::TransactionValidity
|
||||
@@ -34,16 +37,19 @@ pub use codec::{Encode, Decode};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::error;
|
||||
use rstd::vec::Vec;
|
||||
use primitives::OpaqueMetadata;
|
||||
use sr_api_macros::decl_runtime_apis;
|
||||
use primitives::OpaqueMetadata;
|
||||
#[cfg(feature = "std")]
|
||||
use std::panic::UnwindSafe;
|
||||
|
||||
/// Something that can be constructed to a runtime api.
|
||||
#[cfg(feature = "std")]
|
||||
pub trait ConstructRuntimeApi<Block: BlockT> {
|
||||
pub trait ConstructRuntimeApi<Block: BlockT, C: CallRuntimeAt<Block>> {
|
||||
/// The actual runtime api that will be constructed.
|
||||
type RuntimeApi;
|
||||
|
||||
/// Construct an instance of the runtime api.
|
||||
fn construct_runtime_api<'a, T: CallRuntimeAt<Block>>(
|
||||
call: &'a T
|
||||
) -> ApiRef<'a, Self> where Self: Sized;
|
||||
fn construct_runtime_api<'a>(call: &'a C) -> ApiRef<'a, Self::RuntimeApi>;
|
||||
}
|
||||
|
||||
/// An extension for the `RuntimeApi`.
|
||||
@@ -71,14 +77,15 @@ pub trait ApiExt<Block: BlockT> {
|
||||
pub trait CallRuntimeAt<Block: BlockT> {
|
||||
/// Calls the given api function with the given encoded arguments at the given block
|
||||
/// and returns the encoded result.
|
||||
fn call_api_at(
|
||||
fn call_api_at<R: Encode + Decode + PartialEq, NC: FnOnce() -> R + UnwindSafe>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
function: &'static str,
|
||||
args: Vec<u8>,
|
||||
changes: &mut OverlayedChanges,
|
||||
initialised_block: &mut Option<BlockId<Block>>,
|
||||
) -> error::Result<Vec<u8>>;
|
||||
native_call: Option<NC>,
|
||||
) -> error::Result<NativeOrEncoded<R>>;
|
||||
|
||||
/// Returns the runtime version at the given block.
|
||||
fn runtime_version_at(&self, at: &BlockId<Block>) -> error::Result<RuntimeVersion>;
|
||||
@@ -95,7 +102,7 @@ decl_runtime_apis! {
|
||||
/// Execute the given block.
|
||||
fn execute_block(block: Block);
|
||||
/// Initialise a block with the given header.
|
||||
fn initialise_block(header: <Block as BlockT>::Header);
|
||||
fn initialise_block(header: &<Block as BlockT>::Header);
|
||||
}
|
||||
|
||||
/// The `Metadata` api trait that returns metadata for the runtime.
|
||||
|
||||
@@ -492,12 +492,12 @@ impl<B: Block, C, E, MakeInherent, Inherent> Verifier<B> for AuraVerifier<C, E,
|
||||
// actually matches the slot set in the seal.
|
||||
if let Some(inner_body) = body.take() {
|
||||
let inherent = (self.make_inherent)(timestamp_now, slot_num);
|
||||
let block = Block::new(pre_header.clone(), inner_body);
|
||||
let block: B = Block::new(pre_header.clone(), inner_body);
|
||||
|
||||
let inherent_res = self.client.runtime_api().check_inherents(
|
||||
&BlockId::Hash(parent_hash),
|
||||
&block,
|
||||
&inherent,
|
||||
block.clone(),
|
||||
inherent,
|
||||
).map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
match inherent_res {
|
||||
|
||||
@@ -21,10 +21,10 @@ use state_machine::{CodeExecutor, Externalities};
|
||||
use wasm_executor::WasmExecutor;
|
||||
use wasmi::{Module as WasmModule, ModuleRef as WasmModuleInstanceRef};
|
||||
use runtime_version::{NativeVersion, RuntimeVersion};
|
||||
use std::collections::HashMap;
|
||||
use codec::Decode;
|
||||
use std::{collections::HashMap, panic::UnwindSafe};
|
||||
use codec::{Decode, Encode};
|
||||
use RuntimeInfo;
|
||||
use primitives::Blake2Hasher;
|
||||
use primitives::{Blake2Hasher, NativeOrEncoded};
|
||||
use primitives::storage::well_known_keys;
|
||||
|
||||
/// Default num of pages for the heap
|
||||
@@ -95,7 +95,7 @@ fn fetch_cached_runtime_version<'a, E: Externalities<Blake2Hasher>>(
|
||||
}
|
||||
|
||||
fn safe_call<F, U>(f: F) -> Result<U>
|
||||
where F: ::std::panic::UnwindSafe + FnOnce() -> U
|
||||
where F: UnwindSafe + FnOnce() -> U
|
||||
{
|
||||
// Substrate uses custom panic hook that terminates process on panic. Disable it for the native call.
|
||||
let hook = ::std::panic::take_hook();
|
||||
@@ -108,7 +108,7 @@ fn safe_call<F, U>(f: F) -> Result<U>
|
||||
///
|
||||
/// If the inner closure panics, it will be caught and return an error.
|
||||
pub fn with_native_environment<F, U>(ext: &mut Externalities<Blake2Hasher>, f: F) -> Result<U>
|
||||
where F: ::std::panic::UnwindSafe + FnOnce() -> U
|
||||
where F: UnwindSafe + FnOnce() -> U
|
||||
{
|
||||
::runtime_io::with_externalities(ext, move || safe_call(f))
|
||||
}
|
||||
@@ -181,30 +181,78 @@ impl<D: NativeExecutionDispatch> RuntimeInfo for NativeExecutor<D> {
|
||||
impl<D: NativeExecutionDispatch> CodeExecutor<Blake2Hasher> for NativeExecutor<D> {
|
||||
type Error = Error;
|
||||
|
||||
fn call<E: Externalities<Blake2Hasher>>(
|
||||
fn call
|
||||
<
|
||||
E: Externalities<Blake2Hasher>,
|
||||
R:Decode + Encode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe
|
||||
>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
method: &str,
|
||||
data: &[u8],
|
||||
use_native: bool,
|
||||
) -> (Result<Vec<u8>>, bool) {
|
||||
native_call: Option<NC>,
|
||||
) -> (Result<NativeOrEncoded<R>>, bool) {
|
||||
RUNTIMES_CACHE.with(|c| {
|
||||
let mut c = c.borrow_mut();
|
||||
let (module, onchain_version) = match fetch_cached_runtime_version(&self.fallback, &mut c, ext) {
|
||||
Ok((module, onchain_version)) => (module, onchain_version),
|
||||
Err(e) => return (Err(e), false),
|
||||
};
|
||||
match (use_native, onchain_version.as_ref().map_or(false, |v| v.can_call_with(&self.native_version.runtime_version))) {
|
||||
(_, false) => {
|
||||
trace!(target: "executor", "Request for native execution failed (native: {}, chain: {})", self.native_version.runtime_version, onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v)));
|
||||
(self.fallback.call_in_wasm_module(ext, module, method, data), false)
|
||||
match (
|
||||
use_native,
|
||||
onchain_version
|
||||
.as_ref()
|
||||
.map_or(false, |v| v.can_call_with(&self.native_version.runtime_version)),
|
||||
native_call,
|
||||
) {
|
||||
(_, false, _) => {
|
||||
trace!(
|
||||
target: "executor",
|
||||
"Request for native execution failed (native: {}, chain: {})",
|
||||
self.native_version.runtime_version,
|
||||
onchain_version
|
||||
.as_ref()
|
||||
.map_or_else(||"<None>".into(), |v| format!("{}", v))
|
||||
);
|
||||
(
|
||||
self.fallback
|
||||
.call_in_wasm_module(ext, module, method, data)
|
||||
.map(NativeOrEncoded::Encoded),
|
||||
false
|
||||
)
|
||||
}
|
||||
(false, _) => {
|
||||
(self.fallback.call_in_wasm_module(ext, module, method, data), false)
|
||||
(false, _, _) => {
|
||||
(
|
||||
self.fallback
|
||||
.call_in_wasm_module(ext, module, method, data)
|
||||
.map(NativeOrEncoded::Encoded),
|
||||
false
|
||||
)
|
||||
}
|
||||
(true, true, Some(call)) => {
|
||||
trace!(
|
||||
target: "executor",
|
||||
"Request for native execution with native call succeeded (native: {}, chain: {}).",
|
||||
self.native_version.runtime_version,
|
||||
onchain_version
|
||||
.as_ref()
|
||||
.map_or_else(||"<None>".into(), |v| format!("{}", v))
|
||||
);
|
||||
(
|
||||
with_native_environment(ext, move || (call)()).map(NativeOrEncoded::Native),
|
||||
true
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
trace!(target: "executor", "Request for native execution succeeded (native: {}, chain: {})", self.native_version.runtime_version, onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v)));
|
||||
(D::dispatch(ext, method, data), true)
|
||||
trace!(
|
||||
target: "executor",
|
||||
"Request for native execution succeeded (native: {}, chain: {})",
|
||||
self.native_version.runtime_version,
|
||||
onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v))
|
||||
);
|
||||
(D::dispatch(ext, method, data).map(NativeOrEncoded::Encoded), true)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -53,14 +53,6 @@ pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change";
|
||||
/// WASM function call to get current GRANDPA authorities.
|
||||
pub const AUTHORITIES_CALL: &str = "grandpa_authorities";
|
||||
|
||||
/// The ApiIds for GRANDPA API.
|
||||
pub mod id {
|
||||
use client::runtime_api::ApiId;
|
||||
|
||||
/// ApiId for the GrandpaApi trait.
|
||||
pub const GRANDPA_API: ApiId = *b"fgrandpa";
|
||||
}
|
||||
|
||||
/// Well-known storage keys for GRANDPA.
|
||||
pub mod well_known_keys {
|
||||
/// The key for the authorities and weights vector in storage.
|
||||
@@ -92,7 +84,7 @@ decl_runtime_apis! {
|
||||
/// This should be a pure function: i.e. as long as the runtime can interpret
|
||||
/// the digest type it should return the same result regardless of the current
|
||||
/// state.
|
||||
fn grandpa_pending_change(digest: DigestFor<Block>)
|
||||
fn grandpa_pending_change(digest: &DigestFor<Block>)
|
||||
-> Option<ScheduledChange<NumberFor<Block>>>;
|
||||
|
||||
/// Get the current GRANDPA authorities and weights. This should not change except
|
||||
|
||||
@@ -26,7 +26,7 @@ use keyring::Keyring;
|
||||
use client::{
|
||||
BlockchainEvents, error::Result,
|
||||
blockchain::Backend as BlockchainBackend,
|
||||
runtime_api::{Core, RuntimeVersion, ApiExt, ConstructRuntimeApi, CallRuntimeAt},
|
||||
runtime_api::{Core, RuntimeVersion, ApiExt},
|
||||
};
|
||||
use test_client::{self, runtime::BlockNumber};
|
||||
use codec::Decode;
|
||||
@@ -265,7 +265,7 @@ impl Core<Block> for RuntimeApi {
|
||||
unimplemented!("Not required for testing!")
|
||||
}
|
||||
|
||||
fn execute_block(&self, _: &BlockId<Block>, _: &Block) -> Result<()> {
|
||||
fn execute_block(&self, _: &BlockId<Block>, _: Block) -> Result<()> {
|
||||
unimplemented!("Not required for testing!")
|
||||
}
|
||||
|
||||
@@ -291,12 +291,6 @@ impl ApiExt<Block> for RuntimeApi {
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstructRuntimeApi<Block> for RuntimeApi {
|
||||
fn construct_runtime_api<'a, T: CallRuntimeAt<Block>>(_: &'a T) -> ApiRef<'a, Self> {
|
||||
unimplemented!("Not required for testing!")
|
||||
}
|
||||
}
|
||||
|
||||
impl GrandpaApi<Block> for RuntimeApi {
|
||||
fn grandpa_authorities(
|
||||
&self,
|
||||
|
||||
@@ -81,6 +81,8 @@ macro_rules! map {
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd::ops::Deref;
|
||||
#[cfg(feature = "std")]
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use impl_serde::serialize as bytes;
|
||||
@@ -139,7 +141,7 @@ impl Deref for Bytes {
|
||||
}
|
||||
|
||||
/// Stores the encoded `RuntimeMetadata` for the native side as opaque type.
|
||||
#[derive(Encode, Decode)]
|
||||
#[derive(Encode, Decode, PartialEq)]
|
||||
pub struct OpaqueMetadata(Vec<u8>);
|
||||
|
||||
impl OpaqueMetadata {
|
||||
@@ -156,3 +158,72 @@ impl rstd::ops::Deref for OpaqueMetadata {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that is either a native or an encoded value.
|
||||
#[cfg(feature = "std")]
|
||||
pub enum NativeOrEncoded<R> {
|
||||
/// The native representation.
|
||||
Native(R),
|
||||
/// The encoded representation.
|
||||
Encoded(Vec<u8>)
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<R: codec::Encode> ::std::fmt::Debug for NativeOrEncoded<R> {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
self.as_encoded().as_ref().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<R: codec::Encode> NativeOrEncoded<R> {
|
||||
/// Return the value as the encoded format.
|
||||
pub fn as_encoded<'a>(&'a self) -> Cow<'a, [u8]> {
|
||||
match self {
|
||||
NativeOrEncoded::Encoded(e) => Cow::Borrowed(e.as_slice()),
|
||||
NativeOrEncoded::Native(n) => Cow::Owned(n.encode()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the value as the encoded format.
|
||||
pub fn into_encoded(self) -> Vec<u8> {
|
||||
match self {
|
||||
NativeOrEncoded::Encoded(e) => e,
|
||||
NativeOrEncoded::Native(n) => n.encode(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<R: PartialEq + codec::Decode> PartialEq for NativeOrEncoded<R> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(NativeOrEncoded::Native(l), NativeOrEncoded::Native(r)) => l == r,
|
||||
(NativeOrEncoded::Native(n), NativeOrEncoded::Encoded(e)) |
|
||||
(NativeOrEncoded::Encoded(e), NativeOrEncoded::Native(n)) =>
|
||||
Some(n) == codec::Decode::decode(&mut &e[..]).as_ref(),
|
||||
(NativeOrEncoded::Encoded(l), NativeOrEncoded::Encoded(r)) => l == r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A value that is never in a native representation.
|
||||
/// This is type is useful in conjuction with `NativeOrEncoded`.
|
||||
#[cfg(feature = "std")]
|
||||
#[derive(PartialEq)]
|
||||
pub enum NeverNativeValue {}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl codec::Encode for NeverNativeValue {
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
// The enum is not constructable, so this function should never be callable!
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl codec::Decode for NeverNativeValue {
|
||||
fn decode<I: codec::Input>(_: &mut I) -> Option<Self> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +277,9 @@ impl<B, E, Block, RA> StateApi<Block::Hash> for State<B, E, Block, RA> where
|
||||
Block: BlockT<Hash=H256> + 'static,
|
||||
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
|
||||
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
|
||||
RA: Metadata<Block>
|
||||
RA: Send + Sync + 'static,
|
||||
Client<B, E, Block, RA>: ProvideRuntimeApi,
|
||||
<Client<B, E, Block, RA> as ProvideRuntimeApi>::Api: Metadata<Block>
|
||||
{
|
||||
type Metadata = ::metadata::Metadata;
|
||||
|
||||
|
||||
@@ -135,7 +135,8 @@ pub trait StartRPC<C: Components> {
|
||||
}
|
||||
|
||||
impl<C: Components> StartRPC<Self> for C where
|
||||
C::RuntimeApi: Metadata<ComponentBlock<C>>,
|
||||
ComponentClient<C>: ProvideRuntimeApi,
|
||||
<ComponentClient<C> as ProvideRuntimeApi>::Api: Metadata<ComponentBlock<C>>,
|
||||
{
|
||||
type ServersHandle = (Option<rpc::HttpServer>, Option<Mutex<rpc::WsServer>>);
|
||||
|
||||
@@ -189,10 +190,10 @@ fn on_block_imported<Api, Backend, Block, Executor, PoolApi>(
|
||||
client: &Client<Backend, Executor, Block, Api>,
|
||||
transaction_pool: &TransactionPool<PoolApi>,
|
||||
) -> error::Result<()> where
|
||||
Api: TaggedTransactionQueue<Block>,
|
||||
Block: BlockT<Hash = <Blake2Hasher as ::primitives::Hasher>::Out>,
|
||||
Backend: client::backend::Backend<Block, Blake2Hasher>,
|
||||
Client<Backend, Executor, Block, Api>: ProvideRuntimeApi<Api = Api>,
|
||||
Client<Backend, Executor, Block, Api>: ProvideRuntimeApi,
|
||||
<Client<Backend, Executor, Block, Api> as ProvideRuntimeApi>::Api: TaggedTransactionQueue<Block>,
|
||||
Executor: client::CallExecutor<Block, Blake2Hasher>,
|
||||
PoolApi: txpool::ChainApi<Hash = Block::Hash, Block = Block>,
|
||||
{
|
||||
@@ -210,7 +211,7 @@ fn on_block_imported<Api, Backend, Block, Executor, PoolApi>(
|
||||
let parent_id = BlockId::hash(*block.block.header().parent_hash());
|
||||
let mut tags = vec![];
|
||||
for tx in block.block.extrinsics() {
|
||||
let tx = client.runtime_api().validate_transaction(&parent_id, &tx)?;
|
||||
let tx = client.runtime_api().validate_transaction(&parent_id, tx.clone())?;
|
||||
match tx {
|
||||
TransactionValidity::Valid { mut provides, .. } => {
|
||||
tags.append(&mut provides);
|
||||
@@ -230,8 +231,8 @@ fn on_block_imported<Api, Backend, Block, Executor, PoolApi>(
|
||||
}
|
||||
|
||||
impl<C: Components> MaintainTransactionPool<Self> for C where
|
||||
ComponentClient<C>: ProvideRuntimeApi<Api = C::RuntimeApi>,
|
||||
C::RuntimeApi: TaggedTransactionQueue<ComponentBlock<C>>,
|
||||
ComponentClient<C>: ProvideRuntimeApi,
|
||||
<ComponentClient<C> as ProvideRuntimeApi>::Api: TaggedTransactionQueue<ComponentBlock<C>>,
|
||||
{
|
||||
// TODO [ToDr] Optimize and re-use tags from the pool.
|
||||
fn on_block_imported(
|
||||
|
||||
@@ -181,10 +181,7 @@ impl<F: ServiceFactory> TestNet<F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connectivity<F: ServiceFactory, Inherent>(spec: FactoryChainSpec<F>) where
|
||||
<F as ServiceFactory>::RuntimeApi:
|
||||
client::block_builder::api::BlockBuilder<<F as service::ServiceFactory>::Block, Inherent>
|
||||
{
|
||||
pub fn connectivity<F: ServiceFactory, Inherent>(spec: FactoryChainSpec<F>) {
|
||||
const NUM_NODES: u32 = 10;
|
||||
{
|
||||
let temp = TempDir::new("substrate-connectivity-test").expect("Error creating test dir");
|
||||
@@ -228,9 +225,6 @@ where
|
||||
F: ServiceFactory,
|
||||
B: Fn(&F::FullService) -> ImportBlock<F::Block>,
|
||||
E: Fn(&F::FullService) -> FactoryExtrinsic<F>,
|
||||
<F as ServiceFactory>::RuntimeApi:
|
||||
client::block_builder::api::BlockBuilder<<F as service::ServiceFactory>::Block, ()> +
|
||||
client::runtime_api::TaggedTransactionQueue<<F as service::ServiceFactory>::Block>
|
||||
{
|
||||
const NUM_NODES: u32 = 10;
|
||||
const NUM_BLOCKS: usize = 512;
|
||||
@@ -265,10 +259,8 @@ where
|
||||
}
|
||||
|
||||
pub fn consensus<F>(spec: FactoryChainSpec<F>, authorities: Vec<String>)
|
||||
where
|
||||
F: ServiceFactory,
|
||||
<F as ServiceFactory>::RuntimeApi:
|
||||
client::block_builder::api::BlockBuilder<<F as service::ServiceFactory>::Block, ()>
|
||||
where
|
||||
F: ServiceFactory,
|
||||
{
|
||||
const NUM_NODES: u32 = 20;
|
||||
const NUM_BLOCKS: u64 = 200;
|
||||
|
||||
@@ -18,3 +18,8 @@ substrate-test-client = { path = "../test-client" }
|
||||
sr-primitives = { path = "../sr-primitives" }
|
||||
sr-version = { path = "../sr-version" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
criterion = "0.2"
|
||||
|
||||
[[bench]]
|
||||
name = "bench"
|
||||
harness = false
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2018 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/>.
|
||||
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
extern crate substrate_client;
|
||||
extern crate substrate_test_client as test_client;
|
||||
extern crate sr_primitives as runtime_primitives;
|
||||
|
||||
use criterion::Criterion;
|
||||
use test_client::runtime::TestAPI;
|
||||
use runtime_primitives::{generic::BlockId, traits::ProvideRuntimeApi};
|
||||
|
||||
fn sr_api_benchmark(c: &mut Criterion) {
|
||||
c.bench_function("add one with same runtime api", |b| {
|
||||
let client = test_client::new();
|
||||
let runtime_api = client.runtime_api();
|
||||
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
|
||||
|
||||
b.iter(|| runtime_api.benchmark_add_one(&block_id, &1))
|
||||
});
|
||||
|
||||
c.bench_function("add one with recreating runtime api", |b| {
|
||||
let client = test_client::new();
|
||||
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
|
||||
|
||||
b.iter(|| client.runtime_api().benchmark_add_one(&block_id, &1))
|
||||
});
|
||||
|
||||
c.bench_function("vector add one with same runtime api", |b| {
|
||||
let client = test_client::new();
|
||||
let runtime_api = client.runtime_api();
|
||||
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
|
||||
let data = vec![0; 1000];
|
||||
|
||||
b.iter_with_large_drop(|| runtime_api.benchmark_vector_add_one(&block_id, &data))
|
||||
});
|
||||
|
||||
c.bench_function("vector add one with recreating runtime api", |b| {
|
||||
let client = test_client::new();
|
||||
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
|
||||
let data = vec![0; 1000];
|
||||
|
||||
b.iter_with_large_drop(|| client.runtime_api().benchmark_vector_add_one(&block_id, &data))
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, sr_api_benchmark);
|
||||
criterion_main!(benches);
|
||||
@@ -92,24 +92,6 @@ mod adding_at_parameter {
|
||||
*/
|
||||
}
|
||||
|
||||
mod adding_parameter_with_type_reference {
|
||||
/*!
|
||||
```compile_fail
|
||||
#[macro_use]
|
||||
extern crate substrate_client;
|
||||
extern crate sr_primitives as runtime_primitives;
|
||||
|
||||
decl_runtime_apis! {
|
||||
pub trait Api {
|
||||
fn test(data: &u64);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
*/
|
||||
}
|
||||
|
||||
mod invalid_api_version {
|
||||
/*!
|
||||
```compile_fail
|
||||
|
||||
@@ -16,24 +16,28 @@
|
||||
|
||||
use utils::{
|
||||
generate_crate_access, generate_hidden_includes, generate_runtime_mod_name_for_trait,
|
||||
fold_fn_decl_for_client_side, unwrap_or_error
|
||||
fold_fn_decl_for_client_side, unwrap_or_error, extract_parameter_names_types_and_borrows,
|
||||
generate_native_call_generator_fn_name
|
||||
};
|
||||
|
||||
use proc_macro;
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro2::{TokenStream, Span};
|
||||
|
||||
use quote::quote;
|
||||
|
||||
use syn::{
|
||||
spanned::Spanned, parse_macro_input, parse::{Parse, ParseStream, Result, Error},
|
||||
spanned::Spanned, parse_macro_input, parse::{Parse, ParseStream, Result, Error}, ReturnType,
|
||||
fold::{self, Fold}, FnDecl, parse_quote, ItemTrait, Generics, GenericParam, Attribute,
|
||||
visit::{Visit, self}, FnArg, Pat, TraitBound, Type, Meta, NestedMeta, Lit
|
||||
visit::{Visit, self}, FnArg, Pat, TraitBound, Meta, NestedMeta, Lit, TraitItem, Ident, Type
|
||||
};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use blake2_rfc;
|
||||
|
||||
/// The ident used for the block generic parameter.
|
||||
const BLOCK_GENERIC_IDENT: &str = "Block";
|
||||
|
||||
/// Unique identifier used to make the hidden includes unique for this macro.
|
||||
const HIDDEN_INCLUDES_ID: &str = "DECL_RUNTIME_APIS";
|
||||
|
||||
@@ -88,6 +92,167 @@ fn remove_supported_attributes(attrs: &mut Vec<Attribute>) -> HashMap<&'static s
|
||||
result
|
||||
}
|
||||
|
||||
/// Visits the ast and checks if `Block` ident is used somewhere.
|
||||
struct IsUsingBlock {
|
||||
result: bool,
|
||||
}
|
||||
|
||||
impl<'ast> Visit<'ast> for IsUsingBlock {
|
||||
fn visit_ident(&mut self, i: &'ast Ident) {
|
||||
if i == BLOCK_GENERIC_IDENT {
|
||||
self.result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Visits the ast and checks if `Block` ident is used somewhere.
|
||||
fn type_is_using_block(ty: &Type) -> bool {
|
||||
let mut visitor = IsUsingBlock { result: false };
|
||||
visitor.visit_type(ty);
|
||||
visitor.result
|
||||
}
|
||||
|
||||
/// Visits the ast and checks if `Block` ident is used somewhere.
|
||||
fn return_type_is_using_block(ty: &ReturnType) -> bool {
|
||||
let mut visitor = IsUsingBlock { result: false };
|
||||
visitor.visit_return_type(ty);
|
||||
visitor.result
|
||||
}
|
||||
|
||||
/// Replace all occurences of `Block` with `NodeBlock`
|
||||
struct ReplaceBlockWithNodeBlock {}
|
||||
|
||||
impl Fold for ReplaceBlockWithNodeBlock {
|
||||
fn fold_ident(&mut self, input: Ident) -> Ident {
|
||||
if input == BLOCK_GENERIC_IDENT {
|
||||
Ident::new("NodeBlock", Span::call_site())
|
||||
} else {
|
||||
input
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace all occurences of `Block` with `NodeBlock`
|
||||
fn fn_arg_replace_block_with_node_block(fn_arg: FnArg) -> FnArg {
|
||||
let mut replace = ReplaceBlockWithNodeBlock {};
|
||||
fold::fold_fn_arg(&mut replace, fn_arg)
|
||||
}
|
||||
|
||||
/// Replace all occurences of `Block` with `NodeBlock`
|
||||
fn return_type_replace_block_with_node_block(return_type: ReturnType) -> ReturnType {
|
||||
let mut replace = ReplaceBlockWithNodeBlock {};
|
||||
fold::fold_return_type(&mut replace, return_type)
|
||||
}
|
||||
|
||||
fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
|
||||
let fns = decl.items.iter().filter_map(|i| match i {
|
||||
TraitItem::Method(ref m) => Some(&m.sig),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let mut result = Vec::new();
|
||||
let trait_ = &decl.ident;
|
||||
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
|
||||
|
||||
// Auxilariy function that is used to convert between types that use different block types.
|
||||
// The function expects that both a convertable by encoding the one and decoding the other.
|
||||
result.push(quote!(
|
||||
fn convert_between_block_types
|
||||
<I: #crate_::runtime_api::Encode, R: #crate_::runtime_api::Decode>(input: &I) -> R
|
||||
{
|
||||
<R as #crate_::runtime_api::Decode>::decode(
|
||||
&mut &#crate_::runtime_api::Encode::encode(input)[..]
|
||||
).unwrap()
|
||||
}
|
||||
));
|
||||
|
||||
// Generate a native call generator for each function of the given trait.
|
||||
for fn_ in fns {
|
||||
let params = extract_parameter_names_types_and_borrows(&fn_.decl)?;
|
||||
let trait_fn_name = &fn_.ident;
|
||||
let fn_name = generate_native_call_generator_fn_name(&fn_.ident);
|
||||
let output = return_type_replace_block_with_node_block(fn_.decl.output.clone());
|
||||
|
||||
// Every type that is using the `Block` generic parameter, we need to encode/decode,
|
||||
// to make it compatible between the runtime/node.
|
||||
let conversions = params.iter().filter(|v| type_is_using_block(&v.1)).map(|(n, t, _)| {
|
||||
quote!(
|
||||
let #n: #t = convert_between_block_types(&#n);
|
||||
)
|
||||
});
|
||||
// Same as for the input types, we need to check if we also need to convert the output,
|
||||
// before returning it.
|
||||
let output_conversion = if return_type_is_using_block(&fn_.decl.output) {
|
||||
quote!( convert_between_block_types(&res) )
|
||||
} else {
|
||||
quote!( res )
|
||||
};
|
||||
|
||||
let input_names = params.iter().map(|v| &v.0);
|
||||
// If the type is using the block generic type, we will encode/decode it to make it
|
||||
// compatible. To ensure that we forward it by ref/value, we use the value given by the
|
||||
// the user. Otherwise if it is not using the block, we don't need to add anything.
|
||||
let input_borrows = params
|
||||
.iter()
|
||||
.map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { quote!() });
|
||||
|
||||
// Replace all `Block` with `NodeBlock`, add `'a` lifetime to references and collect
|
||||
// all the function inputs.
|
||||
let fn_inputs = fn_
|
||||
.decl
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|v| fn_arg_replace_block_with_node_block(v.clone()))
|
||||
.map(|v| match v {
|
||||
FnArg::Captured(ref arg) => {
|
||||
let mut arg = arg.clone();
|
||||
match arg.ty {
|
||||
Type::Reference(ref mut r) => {
|
||||
r.lifetime = Some(parse_quote!( 'a ));
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
FnArg::Captured(arg)
|
||||
},
|
||||
r => r.clone(),
|
||||
});
|
||||
|
||||
let (impl_generics, ty_generics, where_clause) = decl.generics.split_for_impl();
|
||||
// We need to parse them again, to get an easy access to the actual parameters.
|
||||
let mut impl_generics: Generics = parse_quote!(#impl_generics);
|
||||
let impl_generics_params = impl_generics.params.iter().map(|p| {
|
||||
match p {
|
||||
GenericParam::Type(ref ty) => {
|
||||
let mut ty = ty.clone();
|
||||
ty.bounds.push(parse_quote!( 'a ));
|
||||
GenericParam::Type(ty)
|
||||
},
|
||||
// We should not see anything different than type params here.
|
||||
r => r.clone(),
|
||||
}
|
||||
});
|
||||
|
||||
// Generate the generator function
|
||||
result.push(quote!(
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub fn #fn_name<
|
||||
'a, ApiImpl: #trait_ #ty_generics, NodeBlock: #crate_::runtime_api::BlockT
|
||||
#(, #impl_generics_params)*
|
||||
>(
|
||||
#( #fn_inputs ),*
|
||||
) -> impl FnOnce() #output + 'a #where_clause {
|
||||
move || {
|
||||
#( #conversions )*
|
||||
let res = ApiImpl::#trait_fn_name(#( #input_borrows #input_names ),*);
|
||||
#output_conversion
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
Ok(quote!( #( #result )* ))
|
||||
}
|
||||
|
||||
/// Generate the decleration of the trait for the runtime.
|
||||
fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream {
|
||||
let mut result = Vec::new();
|
||||
@@ -101,9 +266,11 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream {
|
||||
generate_runtime_api_version(v as u32)
|
||||
}));
|
||||
let id = generate_runtime_api_id(&decl.ident.to_string());
|
||||
let native_call_generators = unwrap_or_error(generate_native_call_generators(&decl));
|
||||
|
||||
result.push(quote!(
|
||||
#[doc(hidden)]
|
||||
#[allow(dead_code)]
|
||||
pub mod #mod_name {
|
||||
use super::*;
|
||||
|
||||
@@ -112,6 +279,8 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream {
|
||||
pub #api_version
|
||||
|
||||
pub #id
|
||||
|
||||
#native_call_generators
|
||||
}
|
||||
));
|
||||
}
|
||||
@@ -143,6 +312,7 @@ impl<'a> Fold for ToClientSideDecl<'a> {
|
||||
*self.found_attributes = remove_supported_attributes(&mut input.attrs);
|
||||
// Check if this is the `Core` runtime api trait.
|
||||
let is_core_trait = self.found_attributes.contains_key(CORE_TRAIT_ATTRIBUTE);
|
||||
let block_ident = Ident::new(BLOCK_GENERIC_IDENT, Span::call_site());
|
||||
|
||||
if is_core_trait {
|
||||
// Add all the supertraits we want to have for `Core`.
|
||||
@@ -151,13 +321,12 @@ impl<'a> Fold for ToClientSideDecl<'a> {
|
||||
'static
|
||||
+ Send
|
||||
+ Sync
|
||||
+ #crate_::runtime_api::ConstructRuntimeApi<Block>
|
||||
+ #crate_::runtime_api::ApiExt<Block>
|
||||
+ #crate_::runtime_api::ApiExt<#block_ident>
|
||||
);
|
||||
} else {
|
||||
// Add the `Core` runtime api as super trait.
|
||||
let crate_ = &self.crate_;
|
||||
input.supertraits.push(parse_quote!( #crate_::runtime_api::Core<Block> ));
|
||||
input.supertraits.push(parse_quote!( #crate_::runtime_api::Core<#block_ident> ));
|
||||
}
|
||||
|
||||
// The client side trait is only required when compiling with the feature `std` or `test`.
|
||||
@@ -291,19 +460,6 @@ impl<'ast> Visit<'ast> for CheckTraitDecl {
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match arg.ty {
|
||||
Type::Reference(ref reference) => {
|
||||
self.errors.push(
|
||||
Error::new(
|
||||
reference.span(),
|
||||
"Do not use type references as arguments. The client side \
|
||||
declaration will take all arguments as reference automatically."
|
||||
)
|
||||
)
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
FnArg::SelfRef(_) | FnArg::SelfValue(_) => {
|
||||
self.errors.push(Error::new(input.span(), "Self values are not supported."))
|
||||
@@ -323,7 +479,7 @@ impl<'ast> Visit<'ast> for CheckTraitDecl {
|
||||
|
||||
fn visit_generic_param(&mut self, input: &'ast GenericParam) {
|
||||
match input {
|
||||
GenericParam::Type(ty) if &ty.ident == "Block" => {
|
||||
GenericParam::Type(ty) if &ty.ident == BLOCK_GENERIC_IDENT => {
|
||||
self.errors.push(
|
||||
Error::new(
|
||||
input.span(),
|
||||
@@ -340,7 +496,7 @@ impl<'ast> Visit<'ast> for CheckTraitDecl {
|
||||
|
||||
fn visit_trait_bound(&mut self, input: &'ast TraitBound) {
|
||||
if let Some(last_ident) = input.path.segments.last().map(|v| &v.value().ident) {
|
||||
if last_ident == "BlockT" || last_ident == "Block" {
|
||||
if last_ident == "BlockT" || last_ident == BLOCK_GENERIC_IDENT {
|
||||
self.errors.push(
|
||||
Error::new(
|
||||
input.span(),
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
use utils::{
|
||||
unwrap_or_error, generate_crate_access, generate_hidden_includes,
|
||||
generate_runtime_mod_name_for_trait, fold_fn_decl_for_client_side
|
||||
generate_runtime_mod_name_for_trait, fold_fn_decl_for_client_side, generate_unique_pattern,
|
||||
extract_parameter_names_types_and_borrows, generate_native_call_generator_fn_name
|
||||
};
|
||||
|
||||
use proc_macro;
|
||||
@@ -25,9 +26,9 @@ use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
|
||||
use syn::{
|
||||
spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, MethodSig, FnArg, Path,
|
||||
spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, MethodSig, Path,
|
||||
ImplItem, parse::{Parse, ParseStream, Result, Error}, PathArguments, GenericArgument, TypePath,
|
||||
fold::{self, Fold}, FnDecl, parse_quote, Pat
|
||||
fold::{self, Fold}, FnDecl, parse_quote, FnArg
|
||||
};
|
||||
|
||||
use std::{collections::HashSet, iter};
|
||||
@@ -60,47 +61,17 @@ fn generate_impl_call(
|
||||
input: &Ident,
|
||||
impl_trait: &Path
|
||||
) -> Result<TokenStream> {
|
||||
let mut pnames = Vec::new();
|
||||
let mut ptypes = Vec::new();
|
||||
let mut generated_pattern_counter = 0;
|
||||
for input in signature.decl.inputs.iter() {
|
||||
match input {
|
||||
FnArg::Captured(arg) => {
|
||||
match &arg.ty {
|
||||
Type::Reference(_) => {
|
||||
return Err(
|
||||
Error::new(
|
||||
arg.ty.span(),
|
||||
"No type references are allowed in the api traits!"
|
||||
)
|
||||
)
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
pnames.push(
|
||||
generate_unique_pattern(arg.pat.clone(), &mut generated_pattern_counter)
|
||||
);
|
||||
ptypes.push(&arg.ty);
|
||||
},
|
||||
_ => {
|
||||
return Err(
|
||||
Error::new(
|
||||
input.span(),
|
||||
"Only function arguments with the following \
|
||||
pattern are accepted: `name: type`!"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
let params = extract_parameter_names_types_and_borrows(&signature.decl)?;
|
||||
|
||||
let c = generate_crate_access(HIDDEN_INCLUDES_ID);
|
||||
let c_iter = iter::repeat(&c);
|
||||
let fn_name = &signature.ident;
|
||||
let fn_name_str = iter::repeat(fn_name.to_string());
|
||||
let input = iter::repeat(input);
|
||||
let pnames2 = pnames.clone();
|
||||
let pnames = params.iter().map(|v| &v.0);
|
||||
let pnames2 = params.iter().map(|v| &v.0);
|
||||
let ptypes = params.iter().map(|v| &v.1);
|
||||
let pborrow = params.iter().map(|v| &v.2);
|
||||
|
||||
Ok(
|
||||
quote!(
|
||||
@@ -111,7 +82,7 @@ fn generate_impl_call(
|
||||
};
|
||||
)*
|
||||
|
||||
let output = <#runtime as #impl_trait>::#fn_name(#( #pnames2 ),*);
|
||||
let output = <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*);
|
||||
#c::runtime_api::Encode::encode(&output)
|
||||
).into()
|
||||
)
|
||||
@@ -294,10 +265,11 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
|
||||
let (block, block_id) = generate_node_block_and_block_id_ty(runtime);
|
||||
|
||||
Ok(quote!(
|
||||
pub struct RuntimeApi {}
|
||||
/// Implements all runtime apis for the client side.
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub struct RuntimeApi {
|
||||
call: ::std::ptr::NonNull<#crate_::runtime_api::CallRuntimeAt<#block>>,
|
||||
pub struct RuntimeApiImpl<C: #crate_::runtime_api::CallRuntimeAt<#block> + 'static> {
|
||||
call: &'static C,
|
||||
commit_on_success: ::std::cell::RefCell<bool>,
|
||||
initialised_block: ::std::cell::RefCell<Option<#block_id>>,
|
||||
changes: ::std::cell::RefCell<#crate_::runtime_api::OverlayedChanges>,
|
||||
@@ -307,12 +279,14 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
|
||||
// `ApiRef` object and `ApiRef` also has an associated lifetime. This lifetimes makes it
|
||||
// impossible to move `RuntimeApi` into another thread.
|
||||
#[cfg(any(feature = "std", test))]
|
||||
unsafe impl Send for RuntimeApi {}
|
||||
unsafe impl<C: #crate_::runtime_api::CallRuntimeAt<#block>> Send for RuntimeApiImpl<C> {}
|
||||
#[cfg(any(feature = "std", test))]
|
||||
unsafe impl Sync for RuntimeApi {}
|
||||
unsafe impl<C: #crate_::runtime_api::CallRuntimeAt<#block>> Sync for RuntimeApiImpl<C> {}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl #crate_::runtime_api::ApiExt<#block> for RuntimeApi {
|
||||
impl<C: #crate_::runtime_api::CallRuntimeAt<#block>> #crate_::runtime_api::ApiExt<#block>
|
||||
for RuntimeApiImpl<C>
|
||||
{
|
||||
fn map_api_result<F: FnOnce(&Self) -> ::std::result::Result<R, E>, R, E>(
|
||||
&self,
|
||||
map_call: F
|
||||
@@ -330,22 +304,21 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
|
||||
&self,
|
||||
at: &#block_id
|
||||
) -> #crate_::error::Result<bool> where Self: Sized {
|
||||
unsafe { self.call.as_ref().runtime_version_at(at) }.map(|r| r.has_api::<A>())
|
||||
self.call.runtime_version_at(at).map(|r| r.has_api::<A>())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl #crate_::runtime_api::ConstructRuntimeApi<#block> for RuntimeApi {
|
||||
fn construct_runtime_api<'a, T: #crate_::runtime_api::CallRuntimeAt<#block>>(
|
||||
call: &'a T
|
||||
) -> #crate_::runtime_api::ApiRef<'a, Self> where Self: Sized {
|
||||
RuntimeApi {
|
||||
call: unsafe {
|
||||
::std::ptr::NonNull::new_unchecked(
|
||||
call as
|
||||
&#crate_::runtime_api::CallRuntimeAt<#block> as *const _ as *mut _
|
||||
)
|
||||
},
|
||||
impl<C: #crate_::runtime_api::CallRuntimeAt<#block> + 'static>
|
||||
#crate_::runtime_api::ConstructRuntimeApi<#block, C> for RuntimeApi
|
||||
{
|
||||
type RuntimeApi = RuntimeApiImpl<C>;
|
||||
|
||||
fn construct_runtime_api<'a>(
|
||||
call: &'a C,
|
||||
) -> #crate_::runtime_api::ApiRef<'a, Self::RuntimeApi> {
|
||||
RuntimeApiImpl {
|
||||
call: unsafe { ::std::mem::transmute(call) },
|
||||
commit_on_success: true.into(),
|
||||
initialised_block: None.into(),
|
||||
changes: Default::default(),
|
||||
@@ -354,25 +327,39 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl RuntimeApi {
|
||||
fn call_api_at<A: #crate_::runtime_api::Encode, R: #crate_::runtime_api::Decode>(
|
||||
impl<C: #crate_::runtime_api::CallRuntimeAt<#block>> RuntimeApiImpl<C> {
|
||||
fn call_api_at<
|
||||
R: #crate_::runtime_api::Encode + #crate_::runtime_api::Decode + PartialEq,
|
||||
NC: FnOnce() -> R + ::std::panic::UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
at: &#block_id,
|
||||
function: &'static str,
|
||||
args: &A
|
||||
args: Vec<u8>,
|
||||
native_call: NC,
|
||||
) -> #crate_::error::Result<R> {
|
||||
let res = unsafe {
|
||||
self.call.as_ref().call_api_at(
|
||||
self.call.call_api_at(
|
||||
at,
|
||||
function,
|
||||
args.encode(),
|
||||
args,
|
||||
&mut *self.changes.borrow_mut(),
|
||||
&mut *self.initialised_block.borrow_mut()
|
||||
&mut *self.initialised_block.borrow_mut(),
|
||||
Some(native_call),
|
||||
).and_then(|r|
|
||||
R::decode(&mut &r[..])
|
||||
.ok_or_else(||
|
||||
#crate_::error::ErrorKind::CallResultDecode(function).into()
|
||||
)
|
||||
match r {
|
||||
#crate_::runtime_api::NativeOrEncoded::Native(n) => {
|
||||
Ok(n)
|
||||
},
|
||||
#crate_::runtime_api::NativeOrEncoded::Encoded(r) => {
|
||||
R::decode(&mut &r[..])
|
||||
.ok_or_else(||
|
||||
#crate_::error::ErrorKind::CallResultDecode(
|
||||
function
|
||||
).into()
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
@@ -431,21 +418,6 @@ fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result<TokenStream> {
|
||||
Ok(quote!( #( #impls_prepared )* ))
|
||||
}
|
||||
|
||||
/// Generate an unique pattern based on the given counter, if the given pattern is a `_`.
|
||||
fn generate_unique_pattern(pat: Pat, counter: &mut u32) -> Pat {
|
||||
match pat {
|
||||
Pat::Wild(_) => {
|
||||
let generated_name = Ident::new(
|
||||
&format!("impl_runtime_api_generated_name_{}", counter),
|
||||
pat.span()
|
||||
);
|
||||
*counter += 1;
|
||||
|
||||
parse_quote!( #generated_name )
|
||||
},
|
||||
_ => pat,
|
||||
}
|
||||
}
|
||||
|
||||
/// Auxilariy data structure that is used to convert `impl Api for Runtime` to
|
||||
/// `impl Api for RuntimeApi`.
|
||||
@@ -457,6 +429,9 @@ struct ApiRuntimeImplToApiRuntimeApiImpl<'a> {
|
||||
runtime_block: &'a TypePath,
|
||||
node_block_id: &'a TokenStream,
|
||||
impl_trait_ident: &'a Ident,
|
||||
runtime_mod_path: &'a Path,
|
||||
runtime_type: &'a Type,
|
||||
trait_generic_arguments: &'a [GenericArgument]
|
||||
}
|
||||
|
||||
impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
|
||||
@@ -482,30 +457,63 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
|
||||
}
|
||||
|
||||
fn fold_impl_item_method(&mut self, mut input: syn::ImplItemMethod) -> syn::ImplItemMethod {
|
||||
{
|
||||
let block = {
|
||||
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
|
||||
let mut generated_name_counter = 0;
|
||||
// Replace `_` with unique patterns and collect all patterns.
|
||||
let arg_names = input.sig.decl.inputs.iter_mut().filter_map(|i| match i {
|
||||
FnArg::Captured(ref mut arg) => Some(&mut arg.pat),
|
||||
_ => None,
|
||||
}).map(|p| {
|
||||
*p = generate_unique_pattern(p.clone(), &mut generated_name_counter);
|
||||
p
|
||||
});
|
||||
let name = prefix_function_with_trait(self.impl_trait_ident, &input.sig.ident);
|
||||
p.clone()
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let runtime_mod_path = self.runtime_mod_path;
|
||||
let runtime = self.runtime_type;
|
||||
let arg_names2 = arg_names.clone();
|
||||
let fn_name = prefix_function_with_trait(self.impl_trait_ident, &input.sig.ident);
|
||||
let native_call_generator_ident =
|
||||
generate_native_call_generator_fn_name(&input.sig.ident);
|
||||
let trait_generic_arguments = self.trait_generic_arguments;
|
||||
let node_block = self.node_block;
|
||||
|
||||
// Generate the new method implementation that calls into the runime.
|
||||
input.block = parse_quote!( { self.call_api_at(at, #name, &( #( #arg_names ),* )) } );
|
||||
}
|
||||
parse_quote!(
|
||||
{
|
||||
let args = #crate_::runtime_api::Encode::encode(&( #( &#arg_names ),* ));
|
||||
self.call_api_at(
|
||||
at,
|
||||
#fn_name,
|
||||
args,
|
||||
#runtime_mod_path #native_call_generator_ident ::
|
||||
<#runtime, #node_block #(, #trait_generic_arguments )*> (
|
||||
#( #arg_names2 ),*
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
fold::fold_impl_item_method(self, input)
|
||||
let mut input = fold::fold_impl_item_method(self, input);
|
||||
// We need to set the block, after we modified the rest of the ast, otherwise we would
|
||||
// modify our generated block as well.
|
||||
input.block = block;
|
||||
input
|
||||
}
|
||||
|
||||
fn fold_item_impl(&mut self, mut input: ItemImpl) -> ItemImpl {
|
||||
// Implement the trait for the `RuntimeApi`
|
||||
input.self_ty = Box::new(parse_quote!( RuntimeApi ));
|
||||
// Implement the trait for the `RuntimeApiImpl`
|
||||
input.self_ty = Box::new(parse_quote!( RuntimeApiImpl<RuntimeApiImplCall> ));
|
||||
|
||||
// The implementation for the `RuntimeApi` is only required when compiling with the feature
|
||||
// `std` or `test`.
|
||||
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
|
||||
let block = self.node_block;
|
||||
input.generics.params.push(
|
||||
parse_quote!( RuntimeApiImplCall: #crate_::runtime_api::CallRuntimeAt<#block> + 'static )
|
||||
);
|
||||
|
||||
// The implementation for the `RuntimeApiImpl` is only required when compiling with
|
||||
// the feature `std` or `test`.
|
||||
input.attrs.push(parse_quote!( #[cfg(any(feature = "std", test))] ));
|
||||
|
||||
fold::fold_item_impl(self, input)
|
||||
@@ -517,21 +525,33 @@ fn generate_api_impl_for_runtime_api(impls: &[ItemImpl]) -> Result<TokenStream>
|
||||
let mut result = Vec::with_capacity(impls.len());
|
||||
|
||||
for impl_ in impls {
|
||||
let impl_trait = extract_impl_trait(&impl_)?;
|
||||
let impl_trait_ident = &impl_trait
|
||||
let impl_trait_path = extract_impl_trait(&impl_)?;
|
||||
let impl_trait = &impl_trait_path
|
||||
.segments
|
||||
.last()
|
||||
.ok_or_else(|| Error::new(impl_trait.span(), "Empty trait path not possible!"))?
|
||||
.value()
|
||||
.ident;
|
||||
let runtime_block = extract_runtime_block_ident(impl_trait)?;
|
||||
.ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))?
|
||||
.into_value();
|
||||
let impl_trait_ident = &impl_trait.ident;
|
||||
let runtime_block = extract_runtime_block_ident(impl_trait_path)?;
|
||||
let (node_block, node_block_id) = generate_node_block_and_block_id_ty(&impl_.self_ty);
|
||||
let runtime_type = &impl_.self_ty;
|
||||
let mut runtime_mod_path = extend_with_runtime_decl_path(impl_trait_path.clone());
|
||||
// remove the trait to get just the module path
|
||||
runtime_mod_path.segments.pop();
|
||||
|
||||
let trait_generic_arguments = match impl_trait.arguments {
|
||||
PathArguments::Parenthesized(_) | PathArguments::None => vec![],
|
||||
PathArguments::AngleBracketed(ref b) => b.args.iter().cloned().collect(),
|
||||
};
|
||||
|
||||
let mut visitor = ApiRuntimeImplToApiRuntimeApiImpl {
|
||||
runtime_block,
|
||||
node_block: &node_block,
|
||||
node_block_id: &node_block_id,
|
||||
impl_trait_ident: &impl_trait_ident,
|
||||
runtime_mod_path: &runtime_mod_path,
|
||||
runtime_type: &*runtime_type,
|
||||
trait_generic_arguments: &trait_generic_arguments,
|
||||
};
|
||||
|
||||
result.push(visitor.fold_item_impl(impl_.clone()));
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use proc_macro2::{TokenStream, Span};
|
||||
use syn::{Result, Ident, FnDecl, parse_quote, Type, FnArg};
|
||||
use syn::{Result, Ident, FnDecl, parse_quote, Type, Pat, spanned::Spanned, FnArg, Error};
|
||||
use quote::quote;
|
||||
use std::env;
|
||||
|
||||
@@ -64,19 +64,6 @@ pub fn fold_fn_decl_for_client_side(
|
||||
block_id: &TokenStream,
|
||||
crate_: &TokenStream
|
||||
) -> FnDecl {
|
||||
// Add `&` to all parameter types.
|
||||
input.inputs
|
||||
.iter_mut()
|
||||
.filter_map(|i| match i {
|
||||
FnArg::Captured(ref mut arg) => Some(&mut arg.ty),
|
||||
_ => None,
|
||||
})
|
||||
.filter_map(|i| match i {
|
||||
Type::Reference(_) => None,
|
||||
r => Some(r),
|
||||
})
|
||||
.for_each(|i| *i = parse_quote!( &#i ));
|
||||
|
||||
// Add `&self, at:& BlockId` as parameters to each function at the beginning.
|
||||
input.inputs.insert(0, parse_quote!( at: &#block_id ));
|
||||
input.inputs.insert(0, parse_quote!( &self ));
|
||||
@@ -95,3 +82,61 @@ pub fn fold_fn_decl_for_client_side(
|
||||
|
||||
input
|
||||
}
|
||||
|
||||
/// Generate an unique pattern based on the given counter, if the given pattern is a `_`.
|
||||
pub fn generate_unique_pattern(pat: Pat, counter: &mut u32) -> Pat {
|
||||
match pat {
|
||||
Pat::Wild(_) => {
|
||||
let generated_name = Ident::new(
|
||||
&format!("runtime_api_generated_name_{}", counter),
|
||||
pat.span()
|
||||
);
|
||||
*counter += 1;
|
||||
|
||||
parse_quote!( #generated_name )
|
||||
},
|
||||
_ => pat,
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts the name, the type and `&` or ``(if it is a reference or not)
|
||||
/// for each parameter in the given function declaration.
|
||||
pub fn extract_parameter_names_types_and_borrows(fn_decl: &FnDecl)
|
||||
-> Result<Vec<(Pat, Type, TokenStream)>>
|
||||
{
|
||||
let mut result = Vec::new();
|
||||
let mut generated_pattern_counter = 0;
|
||||
for input in fn_decl.inputs.iter() {
|
||||
match input {
|
||||
FnArg::Captured(arg) => {
|
||||
let (ty, borrow) = match &arg.ty {
|
||||
Type::Reference(t) => {
|
||||
let ty = &t.elem;
|
||||
(parse_quote!( #ty ), quote!( & ))
|
||||
},
|
||||
t => { (t.clone(), quote!()) },
|
||||
};
|
||||
|
||||
let name =
|
||||
generate_unique_pattern(arg.pat.clone(), &mut generated_pattern_counter);
|
||||
result.push((name, ty, borrow));
|
||||
},
|
||||
_ => {
|
||||
return Err(
|
||||
Error::new(
|
||||
input.span(),
|
||||
"Only function arguments with the following \
|
||||
pattern are accepted: `name: type`!"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Generates the name for the native call generator function.
|
||||
pub fn generate_native_call_generator_fn_name(fn_name: &Ident) -> Ident {
|
||||
Ident::new(&format!("{}_native_call_generator", fn_name.to_string()), Span::call_site())
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#[macro_use]
|
||||
extern crate substrate_client;
|
||||
extern crate substrate_client as client;
|
||||
extern crate sr_primitives as runtime_primitives;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_test_client as test_client;
|
||||
|
||||
use runtime_primitives::traits::{GetNodeBlockType, Block as BlockT, AuthorityIdFor};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use substrate_client::runtime_api::{self, RuntimeApiInfo};
|
||||
use substrate_client::error::Result;
|
||||
use client::runtime_api::{self, RuntimeApiInfo};
|
||||
use client::error::Result;
|
||||
use test_client::runtime::Block;
|
||||
|
||||
/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType`
|
||||
@@ -62,17 +62,21 @@ impl_runtime_apis! {
|
||||
fn execute_block(_: Block) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn initialise_block(_: <Block as BlockT>::Header) {
|
||||
fn initialise_block(_: &<Block as BlockT>::Header) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type TestClient = client::Client<test_client::Backend, test_client::Executor, Block, RuntimeApi>;
|
||||
|
||||
#[test]
|
||||
fn test_client_side_function_signature() {
|
||||
let _test: fn(&RuntimeApi, &BlockId<Block>, &u64) -> Result<()> = RuntimeApi::test;
|
||||
let _something_with_block: fn(&RuntimeApi, &BlockId<Block>, &Block) -> Result<Block> =
|
||||
RuntimeApi::something_with_block;
|
||||
let _test: fn(&RuntimeApiImpl<TestClient>, &BlockId<Block>, u64) -> Result<()> =
|
||||
RuntimeApiImpl::<TestClient>::test;
|
||||
let _something_with_block:
|
||||
fn(&RuntimeApiImpl<TestClient>, &BlockId<Block>, Block) -> Result<Block> =
|
||||
RuntimeApiImpl::<TestClient>::something_with_block;
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -531,7 +531,7 @@ impl BasicInherentData {
|
||||
|
||||
//TODO: https://github.com/paritytech/substrate/issues/1022
|
||||
/// Error type used while checking inherents.
|
||||
#[derive(Encode)]
|
||||
#[derive(Encode, PartialEq)]
|
||||
#[cfg_attr(feature = "std", derive(Decode))]
|
||||
pub enum CheckInherentError {
|
||||
/// The inherents are generally valid but a delay until the given timestamp
|
||||
|
||||
@@ -470,7 +470,7 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe
|
||||
type Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec;
|
||||
type Hash: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>;
|
||||
type Hashing: Hash<Output = Self::Hash>;
|
||||
type Digest: Digest<Hash = Self::Hash>;
|
||||
type Digest: Digest<Hash = Self::Hash> + Codec;
|
||||
|
||||
fn new(
|
||||
number: Self::Number,
|
||||
|
||||
@@ -30,15 +30,16 @@ extern crate substrate_trie;
|
||||
|
||||
extern crate parking_lot;
|
||||
extern crate heapsize;
|
||||
#[cfg_attr(test, macro_use)] extern crate substrate_primitives as primitives;
|
||||
#[cfg_attr(test, macro_use)]
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate parity_codec as codec;
|
||||
extern crate substrate_trie as trie;
|
||||
|
||||
use std::fmt;
|
||||
use std::{fmt, panic::UnwindSafe};
|
||||
use hash_db::Hasher;
|
||||
use heapsize::HeapSizeOf;
|
||||
use codec::Decode;
|
||||
use primitives::storage::well_known_keys;
|
||||
use codec::{Decode, Encode};
|
||||
use primitives::{storage::well_known_keys, NativeOrEncoded, NeverNativeValue};
|
||||
|
||||
pub mod backend;
|
||||
mod changes_trie;
|
||||
@@ -171,13 +172,14 @@ pub trait CodeExecutor<H: Hasher>: Sized + Send + Sync {
|
||||
|
||||
/// Call a given method in the runtime. Returns a tuple of the result (either the output data
|
||||
/// or an execution error) together with a `bool`, which is true if native execution was used.
|
||||
fn call<E: Externalities<H>>(
|
||||
fn call<E: Externalities<H>, R: Encode + Decode + PartialEq, NC: FnOnce() -> R + UnwindSafe>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
method: &str,
|
||||
data: &[u8],
|
||||
use_native: bool
|
||||
) -> (Result<Vec<u8>, Self::Error>, bool);
|
||||
use_native: bool,
|
||||
native_call: Option<NC>,
|
||||
) -> (Result<NativeOrEncoded<R>, Self::Error>, bool);
|
||||
}
|
||||
|
||||
/// Strategy for executing a call into the runtime.
|
||||
@@ -213,12 +215,26 @@ impl<'a, F> From<&'a ExecutionManager<F>> for ExecutionStrategy {
|
||||
}
|
||||
|
||||
/// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type.
|
||||
pub fn native_when_possible<E>() -> ExecutionManager<fn(Result<Vec<u8>, E>, Result<Vec<u8>, E>)->Result<Vec<u8>, E>> {
|
||||
pub fn native_when_possible<E, R: Decode>() ->
|
||||
ExecutionManager<
|
||||
fn(
|
||||
Result<NativeOrEncoded<R>, E>,
|
||||
Result<NativeOrEncoded<R>, E>
|
||||
) -> Result<NativeOrEncoded<R>, E>
|
||||
>
|
||||
{
|
||||
ExecutionManager::NativeWhenPossible
|
||||
}
|
||||
|
||||
/// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type.
|
||||
pub fn always_wasm<E>() -> ExecutionManager<fn(Result<Vec<u8>, E>, Result<Vec<u8>, E>)->Result<Vec<u8>, E>> {
|
||||
pub fn always_wasm<E, R: Decode>() ->
|
||||
ExecutionManager<
|
||||
fn(
|
||||
Result<NativeOrEncoded<R>, E>,
|
||||
Result<NativeOrEncoded<R>, E>
|
||||
) -> Result<NativeOrEncoded<R>, E>
|
||||
>
|
||||
{
|
||||
ExecutionManager::AlwaysWasm
|
||||
}
|
||||
|
||||
@@ -246,7 +262,9 @@ where
|
||||
T: ChangesTrieStorage<H>,
|
||||
H::Out: Ord + HeapSizeOf,
|
||||
{
|
||||
execute_using_consensus_failure_handler(
|
||||
// We are not giving a native call and thus we are sure that the result can never be a native
|
||||
// value.
|
||||
execute_using_consensus_failure_handler::<_, _, _, _, _, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
backend,
|
||||
changes_trie_storage,
|
||||
overlay,
|
||||
@@ -257,14 +275,19 @@ where
|
||||
ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm,
|
||||
ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible,
|
||||
ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| {
|
||||
warn!("Consensus error between wasm {:?} and native {:?}. Using wasm.", wasm_result, native_result);
|
||||
warn!(
|
||||
"Consensus error between wasm {:?} and native {:?}. Using wasm.",
|
||||
wasm_result,
|
||||
native_result
|
||||
);
|
||||
wasm_result
|
||||
}),
|
||||
},
|
||||
true,
|
||||
None,
|
||||
)
|
||||
.map(|(result, storage_tx, changes_tx)| (
|
||||
result,
|
||||
result.into_encoded(),
|
||||
storage_tx.expect("storage_tx is always computed when compute_tx is true; qed"),
|
||||
changes_tx,
|
||||
))
|
||||
@@ -278,7 +301,9 @@ where
|
||||
///
|
||||
/// Note: changes to code will be in place if this call is made again. For running partial
|
||||
/// blocks (e.g. a transaction at a time), ensure a different method is used.
|
||||
pub fn execute_using_consensus_failure_handler<H, B, T, Exec, Handler>(
|
||||
pub fn execute_using_consensus_failure_handler<
|
||||
H, B, T, Exec, Handler, R: Decode + Encode + PartialEq, NC: FnOnce() -> R + UnwindSafe
|
||||
>(
|
||||
backend: &B,
|
||||
changes_trie_storage: Option<&T>,
|
||||
overlay: &mut OverlayedChanges,
|
||||
@@ -287,14 +312,18 @@ pub fn execute_using_consensus_failure_handler<H, B, T, Exec, Handler>(
|
||||
call_data: &[u8],
|
||||
manager: ExecutionManager<Handler>,
|
||||
compute_tx: bool,
|
||||
) -> Result<(Vec<u8>, Option<B::Transaction>, Option<MemoryDB<H>>), Box<Error>>
|
||||
mut native_call: Option<NC>,
|
||||
) -> Result<(NativeOrEncoded<R>, Option<B::Transaction>, Option<MemoryDB<H>>), Box<Error>>
|
||||
where
|
||||
H: Hasher,
|
||||
Exec: CodeExecutor<H>,
|
||||
B: Backend<H>,
|
||||
T: ChangesTrieStorage<H>,
|
||||
H::Out: Ord + HeapSizeOf,
|
||||
Handler: FnOnce(Result<Vec<u8>, Exec::Error>, Result<Vec<u8>, Exec::Error>) -> Result<Vec<u8>, Exec::Error>
|
||||
Handler: FnOnce(
|
||||
Result<NativeOrEncoded<R>, Exec::Error>,
|
||||
Result<NativeOrEncoded<R>, Exec::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Exec::Error>
|
||||
{
|
||||
let strategy: ExecutionStrategy = (&manager).into();
|
||||
|
||||
@@ -325,6 +354,7 @@ where
|
||||
call_data,
|
||||
// attempt to run native first, if we're not directed to run wasm only
|
||||
strategy != ExecutionStrategy::AlwaysWasm,
|
||||
native_call.take(),
|
||||
);
|
||||
let (storage_delta, changes_delta) = if compute_tx {
|
||||
let (storage_delta, changes_delta) = externalities.transaction();
|
||||
@@ -351,6 +381,7 @@ where
|
||||
method,
|
||||
call_data,
|
||||
false,
|
||||
native_call,
|
||||
);
|
||||
let (storage_delta, changes_delta) = if compute_tx {
|
||||
let (storage_delta, changes_delta) = externalities.transaction();
|
||||
@@ -363,9 +394,9 @@ where
|
||||
(result, storage_delta, changes_delta)
|
||||
};
|
||||
|
||||
if (result.is_ok() && wasm_result.is_ok() && result.as_ref().unwrap() == wasm_result.as_ref().unwrap()/* && delta == wasm_delta*/)
|
||||
|| (result.is_err() && wasm_result.is_err())
|
||||
{
|
||||
if (result.is_ok() && wasm_result.is_ok()
|
||||
&& result.as_ref().ok() == wasm_result.as_ref().ok())
|
||||
|| result.is_err() && wasm_result.is_err() {
|
||||
(result, storage_delta, changes_delta)
|
||||
} else {
|
||||
// Consensus error.
|
||||
@@ -427,7 +458,9 @@ where
|
||||
H::Out: Ord + HeapSizeOf,
|
||||
{
|
||||
let proving_backend = proving_backend::ProvingBackend::new(trie_backend);
|
||||
let (result, _, _) = execute_using_consensus_failure_handler::<H, _, changes_trie::InMemoryStorage<H>, _, _>(
|
||||
let (result, _, _) = execute_using_consensus_failure_handler::
|
||||
<H, _, changes_trie::InMemoryStorage<H>, _, _, NeverNativeValue, fn() -> NeverNativeValue>
|
||||
(
|
||||
&proving_backend,
|
||||
None,
|
||||
overlay,
|
||||
@@ -436,9 +469,10 @@ where
|
||||
call_data,
|
||||
native_when_possible(),
|
||||
false,
|
||||
None,
|
||||
)?;
|
||||
let proof = proving_backend.extract_proof();
|
||||
Ok((result, proof))
|
||||
Ok((result.into_encoded(), proof))
|
||||
}
|
||||
|
||||
/// Check execution proof, generated by `prove_execution` call.
|
||||
@@ -472,7 +506,9 @@ where
|
||||
Exec: CodeExecutor<H>,
|
||||
H::Out: Ord + HeapSizeOf,
|
||||
{
|
||||
execute_using_consensus_failure_handler::<H, _, changes_trie::InMemoryStorage<H>, _, _>(
|
||||
execute_using_consensus_failure_handler::
|
||||
<H, _, changes_trie::InMemoryStorage<H>, _, _, NeverNativeValue, fn() -> NeverNativeValue>
|
||||
(
|
||||
trie_backend,
|
||||
None,
|
||||
overlay,
|
||||
@@ -481,7 +517,8 @@ where
|
||||
call_data,
|
||||
native_when_possible(),
|
||||
false,
|
||||
).map(|(result, _, _)| result)
|
||||
None,
|
||||
).map(|(result, _, _)| result.into_encoded())
|
||||
}
|
||||
|
||||
/// Generate storage read proof.
|
||||
@@ -588,7 +625,7 @@ mod tests {
|
||||
InMemoryStorage as InMemoryChangesTrieStorage,
|
||||
Configuration as ChangesTrieConfig,
|
||||
};
|
||||
use primitives::{Blake2Hasher};
|
||||
use primitives::Blake2Hasher;
|
||||
|
||||
struct DummyCodeExecutor {
|
||||
change_changes_trie_config: bool,
|
||||
@@ -600,24 +637,41 @@ mod tests {
|
||||
impl<H: Hasher> CodeExecutor<H> for DummyCodeExecutor {
|
||||
type Error = u8;
|
||||
|
||||
fn call<E: Externalities<H>>(
|
||||
fn call<E: Externalities<H>, R: Encode + Decode + PartialEq, NC: FnOnce() -> R>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
_method: &str,
|
||||
_data: &[u8],
|
||||
use_native: bool
|
||||
) -> (Result<Vec<u8>, Self::Error>, bool) {
|
||||
use_native: bool,
|
||||
_native_call: Option<NC>,
|
||||
) -> (Result<NativeOrEncoded<R>, Self::Error>, bool) {
|
||||
if self.change_changes_trie_config {
|
||||
ext.place_storage(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), Some(ChangesTrieConfig {
|
||||
digest_interval: 777,
|
||||
digest_levels: 333,
|
||||
}.encode()));
|
||||
ext.place_storage(
|
||||
well_known_keys::CHANGES_TRIE_CONFIG.to_vec(),
|
||||
Some(
|
||||
ChangesTrieConfig {
|
||||
digest_interval: 777,
|
||||
digest_levels: 333,
|
||||
}.encode()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
let using_native = use_native && self.native_available;
|
||||
match (using_native, self.native_succeeds, self.fallback_succeeds) {
|
||||
(true, true, _) | (false, _, true) =>
|
||||
(Ok(vec![ext.storage(b"value1").unwrap()[0] + ext.storage(b"value2").unwrap()[0]]), using_native),
|
||||
(true, true, _) | (false, _, true) => {
|
||||
(
|
||||
Ok(
|
||||
NativeOrEncoded::Encoded(
|
||||
vec![
|
||||
ext.storage(b"value1").unwrap()[0] +
|
||||
ext.storage(b"value2").unwrap()[0]
|
||||
]
|
||||
)
|
||||
),
|
||||
using_native
|
||||
)
|
||||
},
|
||||
_ => (Err(0), using_native),
|
||||
}
|
||||
}
|
||||
@@ -646,7 +700,7 @@ mod tests {
|
||||
#[test]
|
||||
fn dual_execution_strategy_detects_consensus_failure() {
|
||||
let mut consensus_failed = false;
|
||||
assert!(execute_using_consensus_failure_handler(
|
||||
assert!(execute_using_consensus_failure_handler::<_, _, _, _, _, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&trie_backend::tests::test_trie(),
|
||||
Some(&InMemoryChangesTrieStorage::new()),
|
||||
&mut Default::default(),
|
||||
@@ -664,6 +718,7 @@ mod tests {
|
||||
we
|
||||
}),
|
||||
true,
|
||||
None,
|
||||
).is_err());
|
||||
assert!(consensus_failed);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,12 @@ mod local_executor {
|
||||
#![allow(missing_docs)]
|
||||
use super::runtime;
|
||||
// TODO: change the macro and pass in the `BlakeHasher` that dispatch needs from here instead
|
||||
native_executor_instance!(pub LocalExecutor, runtime::api::dispatch, runtime::native_version, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
|
||||
native_executor_instance!(
|
||||
pub LocalExecutor,
|
||||
runtime::api::dispatch,
|
||||
runtime::native_version,
|
||||
include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")
|
||||
);
|
||||
}
|
||||
|
||||
/// Native executor used for tests.
|
||||
@@ -71,7 +76,9 @@ pub fn new() -> client::Client<Backend, Executor, runtime::Block, runtime::Runti
|
||||
}
|
||||
|
||||
/// Creates new test client instance that suports changes trie creation.
|
||||
pub fn new_with_changes_trie() -> client::Client<Backend, Executor, runtime::Block, runtime::RuntimeApi> {
|
||||
pub fn new_with_changes_trie()
|
||||
-> client::Client<Backend, Executor, runtime::Block, runtime::RuntimeApi>
|
||||
{
|
||||
new_with_backend(Arc::new(Backend::new()), true)
|
||||
}
|
||||
|
||||
@@ -80,9 +87,12 @@ pub fn new_with_changes_trie() -> client::Client<Backend, Executor, runtime::Blo
|
||||
pub fn new_with_backend<B>(
|
||||
backend: Arc<B>,
|
||||
support_changes_trie: bool
|
||||
) -> client::Client<B, client::LocalCallExecutor<B, executor::NativeExecutor<LocalExecutor>>, runtime::Block, runtime::RuntimeApi>
|
||||
where
|
||||
B: backend::LocalBackend<runtime::Block, Blake2Hasher>,
|
||||
) -> client::Client<
|
||||
B,
|
||||
client::LocalCallExecutor<B, executor::NativeExecutor<LocalExecutor>>,
|
||||
runtime::Block,
|
||||
runtime::RuntimeApi
|
||||
> where B: backend::LocalBackend<runtime::Block, Blake2Hasher>
|
||||
{
|
||||
let executor = NativeExecutor::new();
|
||||
client::new_with_backend(backend, executor, genesis_storage(support_changes_trie)).unwrap()
|
||||
|
||||
@@ -32,7 +32,7 @@ use runtime::{self, Transfer};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
|
||||
/// helper to test the `leaves` implementation for various backends
|
||||
pub fn test_leaves_for_backend<B>(backend: Arc<B>) where
|
||||
pub fn test_leaves_for_backend<B: 'static>(backend: Arc<B>) where
|
||||
B: backend::LocalBackend<runtime::Block, Blake2Hasher>,
|
||||
{
|
||||
// block tree:
|
||||
@@ -145,7 +145,7 @@ pub fn test_leaves_for_backend<B>(backend: Arc<B>) where
|
||||
}
|
||||
|
||||
|
||||
pub fn test_blockchain_query_by_number_gets_canonical<B>(backend: Arc<B>) where
|
||||
pub fn test_blockchain_query_by_number_gets_canonical<B: 'static>(backend: Arc<B>) where
|
||||
B: backend::LocalBackend<runtime::Block, Blake2Hasher>,
|
||||
{
|
||||
// block tree:
|
||||
|
||||
@@ -186,13 +186,14 @@ pub fn changes_trie_config() -> primitives::ChangesTrieConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
pub mod test_api {
|
||||
use super::AccountId;
|
||||
|
||||
decl_runtime_apis! {
|
||||
pub trait TestAPI {
|
||||
fn balance_of(id: AccountId) -> u64;
|
||||
}
|
||||
decl_runtime_apis! {
|
||||
pub trait TestAPI {
|
||||
fn balance_of(id: AccountId) -> u64;
|
||||
/// A benchmkark function that adds one to the given value and returns the result.
|
||||
fn benchmark_add_one(val: &u64) -> u64;
|
||||
/// A benchmark function that adds one to each value in the given vector and returns the
|
||||
/// result.
|
||||
fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +221,7 @@ impl_runtime_apis! {
|
||||
system::execute_block(block)
|
||||
}
|
||||
|
||||
fn initialise_block(header: <Block as BlockT>::Header) {
|
||||
fn initialise_block(header: &<Block as BlockT>::Header) {
|
||||
system::initialise_block(header)
|
||||
}
|
||||
}
|
||||
@@ -259,10 +260,20 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl self::test_api::TestAPI<Block> for Runtime {
|
||||
impl self::TestAPI<Block> for Runtime {
|
||||
fn balance_of(id: AccountId) -> u64 {
|
||||
system::balance_of(id)
|
||||
}
|
||||
|
||||
fn benchmark_add_one(val: &u64) -> u64 {
|
||||
val + 1
|
||||
}
|
||||
|
||||
fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64> {
|
||||
let mut vec = vec.clone();
|
||||
vec.iter_mut().for_each(|v| *v += 1);
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
impl aura_api::AuraApi<Block> for Runtime {
|
||||
|
||||
@@ -62,7 +62,7 @@ pub fn authorities() -> Vec<Ed25519AuthorityId> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn initialise_block(header: Header) {
|
||||
pub fn initialise_block(header: &Header) {
|
||||
// populate environment.
|
||||
<Number>::put(&header.number);
|
||||
<ParentHash>::put(&header.parent_hash);
|
||||
|
||||
BIN
Binary file not shown.
@@ -60,7 +60,7 @@ pub trait ChainApi: Send + Sync {
|
||||
type Error: From<error::Error> + error::IntoPoolError;
|
||||
|
||||
/// Verify extrinsic at given block.
|
||||
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: &ExtrinsicFor<Self>) -> Result<TransactionValidity, Self::Error>;
|
||||
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: ExtrinsicFor<Self>) -> Result<TransactionValidity, Self::Error>;
|
||||
|
||||
/// Returns a block number given the block id.
|
||||
fn block_id_to_number(&self, at: &BlockId<Self::Block>) -> Result<Option<NumberFor<Self>>, Self::Error>;
|
||||
@@ -105,10 +105,10 @@ impl<B: ChainApi> Pool<B> {
|
||||
bail!(error::Error::from(error::ErrorKind::TemporarilyBanned))
|
||||
}
|
||||
|
||||
match self.api.validate_transaction(at, &xt)? {
|
||||
match self.api.validate_transaction(at, xt.clone())? {
|
||||
TransactionValidity::Valid { priority, requires, provides, longevity } => {
|
||||
Ok(base::Transaction {
|
||||
data: xt,
|
||||
data: xt,
|
||||
hash,
|
||||
priority,
|
||||
requires,
|
||||
@@ -325,7 +325,7 @@ mod tests {
|
||||
type Error = error::Error;
|
||||
|
||||
/// Verify extrinsic at given block.
|
||||
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: &ExtrinsicFor<Self>) -> Result<TransactionValidity, Self::Error> {
|
||||
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: ExtrinsicFor<Self>) -> Result<TransactionValidity, Self::Error> {
|
||||
let block_number = self.block_id_to_number(at)?.unwrap();
|
||||
let nonce = uxt.transfer().nonce;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ impl<T, Block> txpool::ChainApi for ChainApi<T, Block> where
|
||||
type Hash = H256;
|
||||
type Error = error::Error;
|
||||
|
||||
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: &txpool::ExtrinsicFor<Self>) -> error::Result<TransactionValidity> {
|
||||
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: txpool::ExtrinsicFor<Self>) -> error::Result<TransactionValidity> {
|
||||
Ok(self.client.runtime_api().validate_transaction(at, uxt)?)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ impl txpool::ChainApi for TestApi {
|
||||
type Hash = Hash;
|
||||
type Error = error::Error;
|
||||
|
||||
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: &txpool::ExtrinsicFor<Self>) -> error::Result<TransactionValidity> {
|
||||
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: txpool::ExtrinsicFor<Self>) -> error::Result<TransactionValidity> {
|
||||
let expected = index(at);
|
||||
let requires = if expected == uxt.transfer().nonce {
|
||||
vec![]
|
||||
|
||||
@@ -58,8 +58,9 @@ mod tests {
|
||||
use keyring::Keyring;
|
||||
use runtime_support::{Hashable, StorageValue, StorageMap};
|
||||
use state_machine::{CodeExecutor, Externalities, TestExternalities};
|
||||
use primitives::{twox_128, Blake2Hasher, ChangesTrieConfiguration,
|
||||
ed25519::{Public, Pair}};
|
||||
use primitives::{
|
||||
twox_128, Blake2Hasher, ChangesTrieConfiguration, ed25519::{Public, Pair}, NeverNativeValue
|
||||
};
|
||||
use node_primitives::{Hash, BlockNumber, AccountId};
|
||||
use runtime_primitives::traits::{Header as HeaderT, Digest as DigestT, Hash as HashT};
|
||||
use runtime_primitives::{generic, generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill};
|
||||
@@ -135,10 +136,22 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call(&mut t, "Core_initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_initialise_block",
|
||||
&vec![].and(&from_block_number(1u64)),
|
||||
true,
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
let v = executor().call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0.unwrap();
|
||||
let r = ApplyResult::decode(&mut &v[..]).unwrap();
|
||||
let v = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"BlockBuilder_apply_extrinsic",
|
||||
&vec![].and(&xt()),
|
||||
true,
|
||||
None,
|
||||
).0.unwrap();
|
||||
let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap();
|
||||
assert_eq!(r, Err(ApplyError::CantPay));
|
||||
}
|
||||
|
||||
@@ -156,10 +169,22 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call(&mut t, "Core_initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_initialise_block",
|
||||
&vec![].and(&from_block_number(1u64)),
|
||||
true,
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
let v = executor().call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0.unwrap();
|
||||
let r = ApplyResult::decode(&mut &v[..]).unwrap();
|
||||
let v = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"BlockBuilder_apply_extrinsic",
|
||||
&vec![].and(&xt()),
|
||||
true,
|
||||
None,
|
||||
).0.unwrap();
|
||||
let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap();
|
||||
assert_eq!(r, Err(ApplyError::CantPay));
|
||||
}
|
||||
|
||||
@@ -177,9 +202,21 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call(&mut t, "Core_initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_initialise_block",
|
||||
&vec![].and(&from_block_number(1u64)),
|
||||
true,
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
let r = executor().call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0;
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"BlockBuilder_apply_extrinsic",
|
||||
&vec![].and(&xt()),
|
||||
true,
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
@@ -202,9 +239,21 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call(&mut t, "Core_initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_initialise_block",
|
||||
&vec![].and(&from_block_number(1u64)),
|
||||
true,
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
let r = executor().call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0;
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"BlockBuilder_apply_extrinsic",
|
||||
&vec![].and(&xt()),
|
||||
true,
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
@@ -391,7 +440,13 @@ mod tests {
|
||||
fn full_native_block_import_works() {
|
||||
let mut t = new_test_ext(COMPACT_CODE, false);
|
||||
|
||||
executor().call(&mut t, "Core_execute_block", &block1(false).0, true).0.unwrap();
|
||||
executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block1(false).0,
|
||||
true,
|
||||
None,
|
||||
).0.unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 41);
|
||||
@@ -440,7 +495,13 @@ mod tests {
|
||||
]);
|
||||
});
|
||||
|
||||
executor().call(&mut t, "Core_execute_block", &block2().0, true).0.unwrap();
|
||||
executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block2().0,
|
||||
true,
|
||||
None,
|
||||
).0.unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 30);
|
||||
@@ -686,11 +747,12 @@ mod tests {
|
||||
fn native_big_block_import_succeeds() {
|
||||
let mut t = new_test_ext(COMPACT_CODE, false);
|
||||
|
||||
Executor::new().call(
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block1big().0,
|
||||
true
|
||||
true,
|
||||
None,
|
||||
).0.unwrap();
|
||||
}
|
||||
|
||||
@@ -699,11 +761,12 @@ mod tests {
|
||||
let mut t = new_test_ext(COMPACT_CODE, false);
|
||||
|
||||
assert!(
|
||||
Executor::new().call(
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block1big().0,
|
||||
false
|
||||
false,
|
||||
None,
|
||||
).0.is_err()
|
||||
);
|
||||
}
|
||||
@@ -760,7 +823,13 @@ mod tests {
|
||||
#[test]
|
||||
fn full_native_block_import_works_with_changes_trie() {
|
||||
let mut t = new_test_ext(COMPACT_CODE, true);
|
||||
Executor::new().call(&mut t, "Core_execute_block", &block1(true).0, true).0.unwrap();
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block1(true).0,
|
||||
true,
|
||||
None,
|
||||
).0.unwrap();
|
||||
|
||||
assert!(t.storage_changes_root(Default::default(), 0).is_some());
|
||||
}
|
||||
|
||||
@@ -279,8 +279,8 @@ impl_runtime_apis! {
|
||||
Executive::execute_block(block)
|
||||
}
|
||||
|
||||
fn initialise_block(header: <Block as BlockT>::Header) {
|
||||
Executive::initialise_block(&header)
|
||||
fn initialise_block(header: &<Block as BlockT>::Header) {
|
||||
Executive::initialise_block(header)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ impl_runtime_apis! {
|
||||
}
|
||||
|
||||
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
||||
fn grandpa_pending_change(digest: DigestFor<Block>)
|
||||
fn grandpa_pending_change(digest: &DigestFor<Block>)
|
||||
-> Option<ScheduledChange<NumberFor<Block>>>
|
||||
{
|
||||
for log in digest.logs.iter().filter_map(|l| match l {
|
||||
|
||||
BIN
Binary file not shown.
@@ -30,7 +30,7 @@ pub extern crate sr_primitives as runtime_primitives;
|
||||
extern crate srml_metadata;
|
||||
|
||||
extern crate mashup;
|
||||
#[macro_use]
|
||||
#[cfg_attr(test, macro_use)]
|
||||
extern crate srml_support_procedural;
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user