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:
Bastian Köcher
2019-01-21 14:32:53 +01:00
committed by Gav Wood
parent f0dbcf5401
commit 010e63116f
37 changed files with 1152 additions and 363 deletions
+200
View File
@@ -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(())
+51 -20
View File
@@ -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,
+39 -23
View File
@@ -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())
}
+15 -8
View File
@@ -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.
+3 -3
View File
@@ -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 {
+63 -15
View File
@@ -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
+2 -8
View File
@@ -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,
+72 -1
View File
@@ -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
}
}
+3 -1
View File
@@ -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;
+7 -6
View File
@@ -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(
+3 -11
View File
@@ -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;
+5
View File
@@ -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()));
+59 -14
View File
@@ -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]
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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,
+88 -33
View File
@@ -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);
}
+15 -5
View File
@@ -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:
+20 -9
View File
@@ -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 {
+1 -1
View File
@@ -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);
@@ -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;
+1 -1
View File
@@ -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)?)
}
+1 -1
View File
@@ -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![]
+88 -19
View File
@@ -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());
}
+3 -3
View File
@@ -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 {
+1 -1
View File
@@ -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)]