State Machine: Abstract function execution (#19)

* initial primitives

* add block primitives

* state machine: backend

* in-memory backend

* tests for overlayed storage

* blanked impl for state machine error

* abstract call execution

* squash warnings temporarily

* fix contracts crate

* address grumbles

* remove redundant state-machine dependency
This commit is contained in:
Robert Habermeier
2017-11-13 16:39:58 +01:00
committed by GitHub
parent 2fa0239dab
commit 3dfafb5ec3
10 changed files with 824 additions and 18 deletions
+250
View File
@@ -21,6 +21,15 @@ name = "ansi_term"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "arrayvec"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "assert_matches"
version = "1.1.0"
@@ -60,6 +69,18 @@ dependencies = [
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bigint"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.7.0"
@@ -124,6 +145,14 @@ name = "dtoa"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "elastic-array"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.4.3"
@@ -141,6 +170,40 @@ dependencies = [
"backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethcore-bigint"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethcore-bytes"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ethcore-logger"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fixed-hash"
version = "0.1.0"
@@ -167,11 +230,48 @@ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hashdb"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "heapsize"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "isatty"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "keccak-hash"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@@ -204,11 +304,90 @@ dependencies = [
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memorydb"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nodrop"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num-traits"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "odds"
version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "owning_ref"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "patricia-trie"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-logger 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "plain_hasher"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "polkadot"
version = "0.1.0"
@@ -265,7 +444,12 @@ dependencies = [
name = "polkadot-state-machine"
version = "0.1.0"
dependencies = [
"hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"polkadot-primitives 0.1.0",
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -321,6 +505,18 @@ name = "regex-syntax"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rlp"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.5"
@@ -387,6 +583,16 @@ dependencies = [
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "smallvec"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "stable_deref_trait"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.6.0"
@@ -437,11 +643,32 @@ dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tiny-keccak"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "triehash"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "uint"
version = "0.1.0"
@@ -503,10 +730,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum arrayvec 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "e003cbf6e0e1c43a0fc8df2ea8ea24174514d35cbcf60c35ca6112e0139f65e2"
"checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57"
"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
"checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983"
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d"
@@ -517,18 +746,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85"
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5"
"checksum ethcore-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3977c772cd6c5c22e1c7cfa208e4c3b746bd6c3a6c8eeec0999a6b2103015ad5"
"checksum ethcore-logger 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fd5813e49546030be7d134e775088d56b8ff4ab60617b90e93d4f0513da4c5b"
"checksum fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "<none>"
"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
"checksum hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d97be07c358c5b461268b4ce60304024c5fa5acfd4bd8cd743639f0252003cf5"
"checksum heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54fab2624374e5137ae4df13bf32b0b269cb804df42d13a51221bbd431d1a237"
"checksum isatty 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "00c9301a947a2eaee7ce2556b80285dcc89558d07088962e6e8b9c25730f9dc6"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
"checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5"
"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "013b7e4c5e10c764936ebc6bd3662d8e3c92292d267bf6a42ef3f5cad9c793ee"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e"
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"
"checksum patricia-trie 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2f638d79aba5c4a71a4f373df6e3cd702250a53b7f0ed4da1e2a7be9737ae"
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
"checksum pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94b6bbc8a323d89a019c4cdde21850522fb8405e97add70827177fc2f86c1495"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
@@ -536,6 +781,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
"checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9"
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
@@ -545,13 +791,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3bdafe3e71710131a919735916caa5b18c2754ad0d33d8ae5d586ccc804a403e"
"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab"
"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e"
"checksum smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4f357e8cd37bf8822e1b964e96fd39e2cb5a0424f8aaa284ccaccc2162411c"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
"checksum tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52d12ad79e4063e0cb0ca5efa202ed7244b6ce4d25f4d3abe410b2a66128292"
"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7"
"checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "<none>"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
+2 -2
View File
@@ -15,7 +15,7 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use primitives::Address;
use state_machine::Externalities;
use state_machine::StaticExternalities;
use error::Result;
use executor::RustExecutor;
@@ -32,7 +32,7 @@ impl Contract {
/// Given Message and Authentication Data verifies it and returns:
/// 1. None in case it doesn't match (i.e. signature is invalid)
/// 2. A address who signed that Message.
pub fn check_auth<E: Externalities<RustExecutor>>(&self, _ext: &E, _data: DataAndAuth) -> Result<Option<Address>> {
pub fn check_auth<E: StaticExternalities<RustExecutor>>(&self, _ext: &E, _data: DataAndAuth) -> Result<Option<Address>> {
unimplemented!()
}
}
+4 -4
View File
@@ -16,7 +16,7 @@
use primitives::Address;
use primitives::uint::U256;
use state_machine::Externalities;
use state_machine::{Externalities, StaticExternalities};
use error::Result;
use executor::RustExecutor;
@@ -38,12 +38,12 @@ pub struct Transfer {
pub struct Contract;
impl Contract {
/// Returns a balance of given address.
pub fn balance_of<E: Externalities<RustExecutor>>(&self, _ext: &E, _data: Address) -> Result<U256> {
pub fn balance_of<E: StaticExternalities<RustExecutor>>(&self, _ext: &E, _data: Address) -> Result<U256> {
unimplemented!()
}
/// Returns the next nonce to authorize the transfer from given address.
pub fn next_nonce<E: Externalities<RustExecutor>>(&self, _ext: &E, _data: Address) -> Result<U256> {
pub fn next_nonce<E: StaticExternalities<RustExecutor>>(&self, _ext: &E, _data: Address) -> Result<U256> {
unimplemented!()
}
@@ -52,7 +52,7 @@ impl Contract {
/// - signature
/// - replay protection
/// - enough balance
pub fn transfer_preconditions<E: Externalities<RustExecutor>>(&self, _db: &E, _data: Transfer) -> Result<bool> {
pub fn transfer_preconditions<E: StaticExternalities<RustExecutor>>(&self, _db: &E, _data: Transfer) -> Result<bool> {
unimplemented!()
}
-2
View File
@@ -46,5 +46,3 @@ error_chain! {
}
}
}
impl state_machine::Error for Error {}
+22 -2
View File
@@ -18,7 +18,7 @@
use primitives::contract::{CallData, OutData};
use serializer::{from_slice as de, to_vec as ser};
use state_machine::{Externalities, Executor};
use state_machine::{StaticExternalities, Externalities, Executor};
use error::{Error, ErrorKind, Result};
use auth;
@@ -45,7 +45,7 @@ impl RustExecutor {
impl Executor for RustExecutor {
type Error = Error;
fn static_call<E: Externalities<Self>>(
fn call_static<E: StaticExternalities<Self>>(
&self,
ext: &E,
code: &[u8],
@@ -95,11 +95,31 @@ impl Executor for RustExecutor {
#[cfg(test)]
mod tests {
use super::*;
use primitives::Address;
use primitives::hash::H256;
#[derive(Debug, Default)]
struct TestExternalities;
impl Externalities<RustExecutor> for TestExternalities {
fn set_storage(&mut self, _key: H256, _value: Vec<u8>) {
unimplemented!()
}
fn call(&mut self, _address: &Address, _method: &str, _data: &CallData) -> Result<OutData> {
unimplemented!()
}
}
impl StaticExternalities<RustExecutor> for TestExternalities {
type Error = Error;
fn storage(&self, _key: &H256) -> Result<&[u8]> {
unimplemented!()
}
fn call_static(&self, _address: &Address, _method: &str, _data: &CallData) -> Result<OutData> {
unimplemented!()
}
}
#[test]
+2 -2
View File
@@ -15,7 +15,7 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use primitives::Address;
use state_machine::Externalities;
use state_machine::StaticExternalities;
use error::Result;
use executor::RustExecutor;
@@ -25,7 +25,7 @@ use executor::RustExecutor;
pub struct Contract;
impl Contract {
/// Returns current validator set.
pub fn validator_set<E: Externalities<RustExecutor>>(&self, _db: &E, _data: ()) -> Result<Vec<Address>> {
pub fn validator_set<E: StaticExternalities<RustExecutor>>(&self, _db: &E, _data: ()) -> Result<Vec<Address>> {
unimplemented!()
}
}
+8 -2
View File
@@ -1,7 +1,13 @@
[package]
name = "polkadot-state-machine"
version = "0.1.0"
authors = ["Parity Team <admin@parity.io>"]
authors = ["Parity Technologies <admin@parity.io>"]
description = "Polkadot State Machine"
[dependencies]
polkadot-primitives = { path = "../primitives", version = "0.1" }
polkadot-primitives = { path = "../primitives", version = "0.1.0" }
hashdb = "0.1.1"
keccak-hash = "0.1.0"
patricia-trie = "0.1.0"
memorydb = "0.1.1"
triehash = "0.1"
+108
View File
@@ -0,0 +1,108 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! State machine backends. These manage the code and storage of contracts.
use std::fmt;
use primitives::Address;
use primitives::hash::H256;
use triehash::sec_trie_root;
use super::{Update, MemoryState};
/// Output of a commit.
pub struct Committed {
/// Root of the code tree after changes committed.
pub code_tree_root: H256,
/// Root of the storage tree after changes committed.
pub storage_tree_root: H256,
}
/// A state backend is used to read state data and can have changes committed
/// to it.
pub trait Backend {
/// An error type when fetching data is not possible.
type Error: super::Error;
/// Get code associated with specific address.
fn code(&self, address: &Address) -> Result<&[u8], Self::Error>;
/// Get keyed storage associated with specific address.
fn storage(&self, address: &Address, key: &H256) -> Result<&[u8], Self::Error>;
/// Commit updates to the backend and get new state.
fn commit<I>(&mut self, changes: I) -> Committed
where I: IntoIterator<Item=Update>;
}
/// Error impossible.
// TODO: use `!` type when stabilized.
#[derive(Debug)]
pub enum Void {}
impl fmt::Display for Void {
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
match *self {}
}
}
/// In-memory backend. Fully recomputes tries on each commit but useful for
/// tests.
#[derive(Default)]
pub struct InMemory {
inner: MemoryState, // keeps all the state in memory.
}
impl Backend for InMemory {
type Error = Void;
fn code(&self, address: &Address) -> Result<&[u8], Void> {
Ok(self.inner.code(address).unwrap_or(&[]))
}
fn storage(&self, address: &Address, key: &H256) -> Result<&[u8], Void> {
Ok(self.inner.storage(address, key).unwrap_or(&[]))
}
fn commit<I>(&mut self, changes: I) -> Committed
where I: IntoIterator<Item=Update>
{
self.inner.update(changes);
// fully recalculate trie roots.
let storage_roots = self.inner.storage.iter().map(|(addr, storage)| {
let flat_trie = storage.iter().map(|(k, v)| (k.to_vec(), v.clone())).collect();
(addr.to_vec(), sec_trie_root(flat_trie).to_vec())
}).collect();
let storage_tree_root = H256(sec_trie_root(storage_roots).0);
let code_tree_root = sec_trie_root(
self.inner.code.iter().map(|(k, v)| (k.to_vec(), v.clone())).collect()
);
let code_tree_root = H256(code_tree_root.0);
Committed {
code_tree_root,
storage_tree_root,
}
}
}
// TODO: DB-based backend
+164
View File
@@ -0,0 +1,164 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Conrete externalities implementation.
use std::fmt;
use backend::Backend;
use primitives::Address;
use primitives::contract::{CallData, OutData};
use primitives::hash::H256;
use {Externalities, Executor, StaticExternalities, OverlayedChanges};
/// Errors that can occur when interacting with the externalities.
#[derive(Debug, Copy, Clone)]
pub enum Error<B, E> {
/// Failure to load state data from the backend.
Backend(B),
/// Failure to execute a function.
Executor(E),
}
impl<B: fmt::Display, E: fmt::Display> fmt::Display for Error<B, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Backend(ref e) => write!(f, "Storage backend error: {}", e),
Error::Executor(ref e) => write!(f, "Sub-call execution error: {}", e),
}
}
}
/// Wraps a read-only backend, call executor, and current overlayed changes.
pub struct Ext<'a, B: 'a, E: 'a> {
/// The overlayed changes to write to.
pub overlay: &'a mut OverlayedChanges,
/// The storage backend to read from.
pub backend: &'a B,
/// Contract code executor.
pub exec: &'a E,
/// Contract address.
pub local: Address,
}
impl<'a, B: 'a, E: 'a> StaticExternalities<E> for Ext<'a, B, E>
where B: Backend, E: Executor
{
type Error = Error<B::Error, E::Error>;
fn storage(&self, key: &H256) -> Result<&[u8], Self::Error> {
match self.overlay.storage(&self.local, key) {
Some(x) => Ok(x),
None => self.backend.storage(&self.local, key).map_err(Error::Backend)
}
}
fn call_static(&self, address: &Address, method: &str, data: &CallData) -> Result<OutData, Self::Error> {
let inner_ext = StaticExt {
backend: self.backend,
exec: self.exec,
local: address.clone(),
overlay: self.overlay,
};
let code = match self.overlay.code(address) {
Some(x) => x,
None => self.backend.code(address).map_err(Error::Backend)?,
};
self.exec.call_static(
&inner_ext,
code,
method,
data,
).map_err(Error::Executor)
}
}
impl<'a, B: 'a, E: 'a> Externalities<E> for Ext<'a, B, E>
where B: Backend, E: Executor
{
fn set_storage(&mut self, key: H256, value: Vec<u8>) {
self.overlay.set_storage(self.local, key, value);
}
fn call(&mut self, address: &Address, method: &str, data: &CallData) -> Result<OutData, Self::Error> {
let code = {
let code = match self.overlay.code(address) {
Some(x) => x,
None => self.backend.code(address).map_err(Error::Backend)?,
};
code.to_owned()
};
let mut inner_ext = Ext {
backend: self.backend,
exec: self.exec,
local: address.clone(),
overlay: &mut *self.overlay,
};
self.exec.call(
&mut inner_ext,
&code[..],
method,
data,
).map_err(Error::Executor)
}
}
// Static externalities
struct StaticExt<'a, B: 'a, E: 'a> {
overlay: &'a OverlayedChanges,
backend: &'a B,
exec: &'a E,
local: Address,
}
impl<'a, B: 'a, E: 'a> StaticExternalities<E> for StaticExt<'a, B, E>
where B: Backend, E: Executor
{
type Error = Error<B::Error, E::Error>;
fn storage(&self, key: &H256) -> Result<&[u8], Self::Error> {
match self.overlay.storage(&self.local, key) {
Some(x) => Ok(x),
None => self.backend.storage(&self.local, key).map_err(Error::Backend)
}
}
fn call_static(&self, address: &Address, method: &str, data: &CallData) -> Result<OutData, Self::Error> {
let inner_ext = StaticExt {
backend: self.backend,
exec: self.exec,
local: address.clone(),
overlay: self.overlay,
};
let code = match self.overlay.code(address) {
Some(x) => x,
None => self.backend.code(address).map_err(Error::Backend)?,
};
self.exec.call_static(
&inner_ext,
code,
method,
data,
).map_err(Error::Executor)
}
}
+264 -4
View File
@@ -14,25 +14,182 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Polkadot state machine
//! Polkadot state machine implementation.
#![warn(missing_docs)]
extern crate polkadot_primitives as primitives;
extern crate hashdb;
extern crate memorydb;
extern crate keccak_hash;
extern crate patricia_trie;
extern crate triehash;
use std::collections::HashMap;
use std::fmt;
use primitives::Address;
use primitives::contract::{CallData, OutData};
use primitives::hash::H256;
pub mod backend;
mod ext;
/// Updates to be committed to the state.
pub enum Update {
/// Set storage of address at given key -- empty is deletion.
Storage(Address, H256, Vec<u8>),
/// Set code of address -- empty is deletion.
Code(Address, Vec<u8>),
}
// in-memory section of the state.
#[derive(Default)]
struct MemoryState {
code: HashMap<Address, Vec<u8>>,
storage: HashMap<Address, HashMap<H256, Vec<u8>>>,
}
impl MemoryState {
fn code(&self, address: &Address) -> Option<&[u8]> {
self.code.get(address).map(|v| &v[..])
}
fn storage(&self, address: &Address, key: &H256) -> Option<&[u8]> {
self.storage.get(address)
.and_then(|m| m.get(key))
.map(|v| &v[..])
}
#[allow(unused)]
fn set_code(&mut self, address: Address, code: Vec<u8>) {
self.code.insert(address, code);
}
fn set_storage(&mut self, address: Address, key: H256, val: Vec<u8>) {
self.storage.entry(address)
.or_insert_with(HashMap::new)
.insert(key, val);
}
fn update<I>(&mut self, changes: I) where I: IntoIterator<Item=Update> {
for update in changes {
match update {
Update::Storage(addr, key, val) => {
if val.is_empty() {
let mut empty = false;
if let Some(s) = self.storage.get_mut(&addr) {
s.remove(&key);
empty = s.is_empty();
};
if empty { self.storage.remove(&addr); }
} else {
self.storage.entry(addr)
.or_insert_with(HashMap::new)
.insert(key, val);
}
}
Update::Code(addr, code) => {
if code.is_empty() {
self.code.remove(&addr);
} else {
self.code.insert(addr, code);
}
}
}
}
}
}
/// The overlayed changes to state to be queried on top of the backend.
///
/// A transaction shares all prospective changes within an inner overlay
/// that can be cleared.
#[derive(Default)]
pub struct OverlayedChanges {
prospective: MemoryState,
committed: MemoryState,
}
impl OverlayedChanges {
fn code(&self, address: &Address) -> Option<&[u8]> {
self.prospective.code(address)
.or_else(|| self.committed.code(address))
.and_then(|v| if v.is_empty() { None } else { Some(v) })
}
fn storage(&self, address: &Address, key: &H256) -> Option<&[u8]> {
self.prospective.storage(address, key)
.or_else(|| self.committed.storage(address, key))
.and_then(|v| if v.is_empty() { None } else { Some(v) })
}
#[allow(unused)]
fn set_code(&mut self, address: Address, code: Vec<u8>) {
self.prospective.set_code(address, code);
}
fn set_storage(&mut self, address: Address, key: H256, val: Vec<u8>) {
self.prospective.set_storage(address, key, val);
}
/// Discard prospective changes to state.
pub fn discard_prospective(&mut self) {
self.prospective.code.clear();
self.prospective.storage.clear();
}
/// Commit prospective changes to state.
pub fn commit_prospective(&mut self) {
let code_updates = self.prospective.code.drain()
.map(|(addr, code)| Update::Code(addr, code));
let storage_updates = self.prospective.storage.drain()
.flat_map(|(addr, storages)| storages.into_iter().map(move |(k, v)| (addr, k, v)))
.map(|(addr, key, value)| Update::Storage(addr, key, value));
self.committed.update(code_updates.chain(storage_updates));
}
}
/// State Machine Error bound.
///
/// This should reflect WASM error type bound for future compatibility.
pub trait Error: 'static + fmt::Debug + fmt::Display + Send {}
impl<E> Error for E where E: 'static + fmt::Debug + fmt::Display + Send {}
/// Externalities
pub trait Externalities<Executor> {
/// Externalities: pinned to specific active address.
pub trait Externalities<Executor>: StaticExternalities<Executor> {
/// Read storage of current contract being called.
fn storage(&self, key: &H256) -> Result<&[u8], Self::Error> {
StaticExternalities::storage(self, key)
}
/// Set storage of current contract being called.
fn set_storage(&mut self, key: H256, value: Vec<u8>);
/// Make a sub-call to another contract.
fn call(&mut self, address: &Address, method: &str, data: &CallData) -> Result<OutData, Self::Error>;
/// Make a static (read-only) call to another contract.
fn call_static(&self, address: &Address, method: &str, data: &CallData) -> Result<OutData, Self::Error> {
StaticExternalities::call_static(self, address, method, data)
}
}
/// Static externalities: used only for read-only requests.
pub trait StaticExternalities<Executor> {
/// Externalities error type.
type Error: Error;
/// Read storage of current contract being called.
fn storage(&self, key: &H256) -> Result<&[u8], Self::Error>;
/// Make a static (read-only) call to another contract.
fn call_static(&self, address: &Address, method: &str, data: &CallData) -> Result<OutData, Self::Error>;
}
/// Contract code executor.
@@ -42,7 +199,7 @@ pub trait Executor: Sized {
/// Execute a contract in read-only mode.
/// The execution is not allowed to modify the state.
fn static_call<E: Externalities<Self>>(
fn call_static<E: StaticExternalities<Self>>(
&self,
ext: &E,
code: &[u8],
@@ -59,3 +216,106 @@ pub trait Executor: Sized {
data: &CallData,
) -> Result<OutData, Self::Error>;
}
/// Execute a call using the given state backend, overlayed changes, and call executor.
///
/// On an error, no prospective changes are written to the overlay.
pub fn execute<B: backend::Backend, Exec: Executor>(
backend: &B,
overlay: &mut OverlayedChanges,
exec: &Exec,
address: &Address,
method: &str,
call_data: &CallData,
) -> Result<OutData, Box<Error>> {
let code = match overlay.code(address) {
Some(x) => x.to_owned(),
None => backend.code(address).map_err(|e| Box::new(e) as _)?.to_owned(),
};
let result = {
let mut externalities = ext::Ext {
backend,
exec,
overlay: &mut *overlay,
local: *address,
};
exec.call(
&mut externalities,
&code[..],
method,
call_data,
)
};
match result {
Ok(out) => {
overlay.commit_prospective();
Ok(out)
}
Err(e) => {
overlay.discard_prospective();
Err(Box::new(e))
}
}
}
#[cfg(test)]
mod tests {
use super::OverlayedChanges;
use primitives::hash::H256;
use primitives::Address;
#[test]
fn overlayed_storage_works() {
let mut overlayed = OverlayedChanges::default();
let key = H256::random();
let addr = Address::random();
assert!(overlayed.storage(&addr, &key).is_none());
overlayed.set_storage(addr, key, vec![1, 2, 3]);
assert_eq!(overlayed.storage(&addr, &key).unwrap(), &[1, 2, 3]);
overlayed.commit_prospective();
assert_eq!(overlayed.storage(&addr, &key).unwrap(), &[1, 2, 3]);
overlayed.set_storage(addr, key, vec![]);
assert!(overlayed.storage(&addr, &key).is_none());
overlayed.discard_prospective();
assert_eq!(overlayed.storage(&addr, &key).unwrap(), &[1, 2, 3]);
overlayed.set_storage(addr, key, vec![]);
overlayed.commit_prospective();
assert!(overlayed.storage(&addr, &key).is_none());
}
#[test]
fn overlayed_code_works() {
let mut overlayed = OverlayedChanges::default();
let addr = Address::random();
assert!(overlayed.code(&addr).is_none());
overlayed.set_code(addr, vec![1, 2, 3]);
assert_eq!(overlayed.code(&addr).unwrap(), &[1, 2, 3]);
overlayed.commit_prospective();
assert_eq!(overlayed.code(&addr).unwrap(), &[1, 2, 3]);
overlayed.set_code(addr, vec![]);
assert!(overlayed.code(&addr).is_none());
overlayed.discard_prospective();
assert_eq!(overlayed.code(&addr).unwrap(), &[1, 2, 3]);
overlayed.set_code(addr, vec![]);
overlayed.commit_prospective();
assert!(overlayed.code(&addr).is_none());
}
}