fixed evm tests
This commit is contained in:
commit
017430e803
59
CHANGELOG.md
59
CHANGELOG.md
@ -1,41 +1,45 @@
|
|||||||
## Parity [v1.6.10](https://github.com/paritytech/parity/releases/tag/v1.6.10) (2017-07-23)
|
## Parity [v1.7.0](https://github.com/paritytech/parity/releases/tag/v1.7.0) (2017-07-28)
|
||||||
|
|
||||||
This is a hotfix release for the stable channel addressing the recent [multi-signature wallet vulnerability](https://blog.parity.io/security-alert-high-2/). Note, upgrading is not mandatory, and all future multi-sig wallets created by any version of Parity are secure.
|
|
||||||
|
|
||||||
All Changes:
|
|
||||||
|
|
||||||
- Backports for stable [#6116](https://github.com/paritytech/parity/pull/6116)
|
|
||||||
- Remove chunk to restore from pending set only upon successful import [#6112](https://github.com/paritytech/parity/pull/6112)
|
|
||||||
- Blacklist bad snapshot manifest hashes upon failure [#5874](https://github.com/paritytech/parity/pull/5874)
|
|
||||||
- Bump snap version and tweak importing detection logic [#6079](https://github.com/paritytech/parity/pull/6079) (modified to work)
|
|
||||||
- Fix docker build for stable [#6118](https://github.com/paritytech/parity/pull/6118)
|
|
||||||
- Backported wallet fix [#6104](https://github.com/paritytech/parity/pull/6104)
|
|
||||||
- Fix initialisation bug. ([#6102](https://github.com/paritytech/parity/pull/6102))
|
|
||||||
- Update wallet library modifiers ([#6103](https://github.com/paritytech/parity/pull/6103))
|
|
||||||
- Bump to v1.6.10
|
|
||||||
|
|
||||||
## Parity [v1.7.0](https://github.com/paritytech/parity/releases/tag/v1.7.0) (2017-07-23)
|
|
||||||
|
|
||||||
Parity 1.7.0 is a major release introducing several important features:
|
Parity 1.7.0 is a major release introducing several important features:
|
||||||
|
|
||||||
- **Experimental [Light client](https://github.com/paritytech/parity/wiki/The-Parity-Light-Protocol-(PIP)) support**. Start Parity with `--light` to enable light mode.
|
- **Experimental [Light client](https://github.com/paritytech/parity/wiki/The-Parity-Light-Protocol-(PIP)) support**. Start Parity with `--light` to enable light mode. Please, note: The wallet UI integration for the light client is not included, yet.
|
||||||
- **Experimental web wallet**. A hosted version of Parity that keeps the keys and signs transactions using your browser storage. Try it at https://wallet.parity.io or run your own with `--public-node`.
|
- **Experimental web wallet**. A hosted version of Parity that keeps the keys and signs transactions using your browser storage. Try it at https://wallet.parity.io or run your own with `--public-node`.
|
||||||
- **WASM contract support**. Private networks can run contracts compiled into WASM bytecode. _More information and documentation to follow_.
|
- **WASM contract support**. Private networks can run contracts compiled into WASM bytecode. _More information and documentation to follow_.
|
||||||
- **DApps and RPC server merge**. DApp and RPC are now available through a single API endpoint. DApp server related settings are deprecated.
|
- **DApps and RPC server merge**. DApp and RPC are now available through a single API endpoint. DApp server related settings are deprecated.
|
||||||
- **Export accounts from the wallet**. Backing up your keys can now simply be managed through the wallet interface.
|
- **Export accounts from the wallet**. Backing up your keys can now simply be managed through the wallet interface.
|
||||||
- **PoA/Kovan validator set contract**. The PoA network validator-set management via smart contract is now supported by warp and light sync.
|
- **PoA/Kovan validator set contract**. The PoA network validator-set management via smart contract is now supported by warp and, in the near future, light sync.
|
||||||
- **PubSub API**. https://github.com/paritytech/parity/wiki/JSONRPC-Parity-Pub-Sub-module
|
- **PubSub API**. https://github.com/paritytech/parity/wiki/JSONRPC-Parity-Pub-Sub-module
|
||||||
- **Signer apps for IOS and Android**.
|
- **Signer apps for IOS and Android**.
|
||||||
|
|
||||||
Full list of included changes:
|
Full list of included changes:
|
||||||
|
|
||||||
|
- Backports [#6163](https://github.com/paritytech/parity/pull/6163)
|
||||||
|
- Light client improvements ([#6156](https://github.com/paritytech/parity/pull/6156))
|
||||||
|
- No seal checking
|
||||||
|
- Import command and --no-seal-check for light client
|
||||||
|
- Fix eth_call
|
||||||
|
- Tweak registry dapps lookup
|
||||||
|
- Ignore failed requests to non-server peers
|
||||||
|
- Fix connecting to wildcard addresses. ([#6167](https://github.com/paritytech/parity/pull/6167))
|
||||||
|
- Don't display an overlay in case the time sync check fails. ([#6164](https://github.com/paritytech/parity/pull/6164))
|
||||||
|
- Small improvements to time estimation.
|
||||||
|
- Temporarily disable NTP time check by default.
|
||||||
|
- Light client fixes ([#6148](https://github.com/paritytech/parity/pull/6148)) [#6151](https://github.com/paritytech/parity/pull/6151)
|
||||||
|
- Light client fixes
|
||||||
|
- Fix memory-lru-cache
|
||||||
|
- Clear pending reqs on disconnect
|
||||||
|
- Filter tokens logs from current block, not genesis ([#6128](https://github.com/paritytech/parity/pull/6128)) [#6141](https://github.com/paritytech/parity/pull/6141)
|
||||||
|
- Fix QR scanner returning null on confirm [#6122](https://github.com/paritytech/parity/pull/6122)
|
||||||
- Check QR before lowercase ([#6119](https://github.com/paritytech/parity/pull/6119)) [#6120](https://github.com/paritytech/parity/pull/6120)
|
- Check QR before lowercase ([#6119](https://github.com/paritytech/parity/pull/6119)) [#6120](https://github.com/paritytech/parity/pull/6120)
|
||||||
- Remove chunk to restore from pending set only upon successful import [#6117](https://github.com/paritytech/parity/pull/6117)
|
- Remove chunk to restore from pending set only upon successful import [#6117](https://github.com/paritytech/parity/pull/6117)
|
||||||
- Fixed node address detection on incoming connection [#6094](https://github.com/paritytech/parity/pull/6094)
|
- Fixed node address detection on incoming connection [#6094](https://github.com/paritytech/parity/pull/6094)
|
||||||
- Place RETURNDATA behind block number gate [#6095](https://github.com/paritytech/parity/pull/6095)
|
- Place RETURNDATA behind block number gate [#6095](https://github.com/paritytech/parity/pull/6095)
|
||||||
|
- Update wallet library binaries [#6108](https://github.com/paritytech/parity/pull/6108)
|
||||||
- Backported wallet fix [#6105](https://github.com/paritytech/parity/pull/6105)
|
- Backported wallet fix [#6105](https://github.com/paritytech/parity/pull/6105)
|
||||||
- Fix initialisation bug. ([#6102](https://github.com/paritytech/parity/pull/6102))
|
- Fix initialisation bug. ([#6102](https://github.com/paritytech/parity/pull/6102))
|
||||||
- Update wallet library modifiers ([#6103](https://github.com/paritytech/parity/pull/6103))
|
- Update wallet library modifiers ([#6103](https://github.com/paritytech/parity/pull/6103))
|
||||||
|
- Place RETURNDATA behind block number gate [#6095](https://github.com/paritytech/parity/pull/6095)
|
||||||
|
- Fixed node address detection on incoming connection [#6094](https://github.com/paritytech/parity/pull/6094)
|
||||||
- Bump snap version and tweak importing detection logic ([#6079](https://github.com/paritytech/parity/pull/6079)) [#6081](https://github.com/paritytech/parity/pull/6081)
|
- Bump snap version and tweak importing detection logic ([#6079](https://github.com/paritytech/parity/pull/6079)) [#6081](https://github.com/paritytech/parity/pull/6081)
|
||||||
- bump last tick just before printing info and restore sync detection
|
- bump last tick just before printing info and restore sync detection
|
||||||
- bump kovan snapshot version
|
- bump kovan snapshot version
|
||||||
@ -439,6 +443,23 @@ Full list of included changes:
|
|||||||
- Update the Wallet Library Registry key [#4817](https://github.com/paritytech/parity/pull/4817)
|
- Update the Wallet Library Registry key [#4817](https://github.com/paritytech/parity/pull/4817)
|
||||||
- Update Wallet to new Wallet Code [#4805](https://github.com/paritytech/parity/pull/4805)
|
- Update Wallet to new Wallet Code [#4805](https://github.com/paritytech/parity/pull/4805)
|
||||||
|
|
||||||
|
## Parity [v1.6.10](https://github.com/paritytech/parity/releases/tag/v1.6.10) (2017-07-25)
|
||||||
|
|
||||||
|
This is a hotfix release for the stable channel addressing the recent [multi-signature wallet vulnerability](https://blog.parity.io/security-alert-high-2/). Note, upgrading is not mandatory, and all future multi-sig wallets created by any version of Parity are secure.
|
||||||
|
|
||||||
|
All Changes:
|
||||||
|
|
||||||
|
- Backports for stable [#6116](https://github.com/paritytech/parity/pull/6116)
|
||||||
|
- Remove chunk to restore from pending set only upon successful import [#6112](https://github.com/paritytech/parity/pull/6112)
|
||||||
|
- Blacklist bad snapshot manifest hashes upon failure [#5874](https://github.com/paritytech/parity/pull/5874)
|
||||||
|
- Bump snap version and tweak importing detection logic [#6079](https://github.com/paritytech/parity/pull/6079) (modified to work)
|
||||||
|
- Fix docker build for stable [#6118](https://github.com/paritytech/parity/pull/6118)
|
||||||
|
- Update wallet library binaries [#6108](https://github.com/paritytech/parity/pull/6108)
|
||||||
|
- Backported wallet fix [#6104](https://github.com/paritytech/parity/pull/6104)
|
||||||
|
- Fix initialisation bug. ([#6102](https://github.com/paritytech/parity/pull/6102))
|
||||||
|
- Update wallet library modifiers ([#6103](https://github.com/paritytech/parity/pull/6103))
|
||||||
|
- Bump to v1.6.10
|
||||||
|
|
||||||
## Parity [v1.6.9](https://github.com/paritytech/parity/releases/tag/v1.6.9) (2017-07-16)
|
## Parity [v1.6.9](https://github.com/paritytech/parity/releases/tag/v1.6.9) (2017-07-16)
|
||||||
|
|
||||||
This is a first stable release of 1.6 series. It contains a number of minor fixes and introduces the `--reseal-on-uncles` option for miners.
|
This is a first stable release of 1.6 series. It contains a number of minor fixes and introduces the `--reseal-on-uncles` option for miners.
|
||||||
|
51
Cargo.lock
generated
51
Cargo.lock
generated
@ -1,6 +1,15 @@
|
|||||||
[root]
|
[root]
|
||||||
name = "using_queue"
|
name = "wasm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ethcore-logger 1.8.0",
|
||||||
|
"ethcore-util 1.8.0",
|
||||||
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"vm 0.1.0",
|
||||||
|
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "advapi32-sys"
|
name = "advapi32-sys"
|
||||||
@ -504,6 +513,8 @@ dependencies = [
|
|||||||
"stats 0.1.0",
|
"stats 0.1.0",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"vm 0.1.0",
|
||||||
|
"wasm 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -625,6 +636,7 @@ dependencies = [
|
|||||||
"smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"stats 0.1.0",
|
"stats 0.1.0",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"vm 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -656,6 +668,7 @@ dependencies = [
|
|||||||
"ethcrypto 0.1.0",
|
"ethcrypto 0.1.0",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ipnetwork 0.12.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -776,7 +789,7 @@ name = "ethjson"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-util 1.8.0",
|
"ethcore-bigint 0.1.3",
|
||||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -862,6 +875,7 @@ dependencies = [
|
|||||||
"ethcore-util 1.8.0",
|
"ethcore-util 1.8.0",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ipnetwork 0.12.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -887,6 +901,7 @@ dependencies = [
|
|||||||
"parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rlp 0.2.0",
|
"rlp 0.2.0",
|
||||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"vm 0.1.0",
|
||||||
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
|
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1150,6 +1165,11 @@ dependencies = [
|
|||||||
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipnetwork"
|
||||||
|
version = "0.12.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "isatty"
|
name = "isatty"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -1764,6 +1784,7 @@ dependencies = [
|
|||||||
"ethcore-ipc-tests 0.1.0",
|
"ethcore-ipc-tests 0.1.0",
|
||||||
"ethcore-light 1.8.0",
|
"ethcore-light 1.8.0",
|
||||||
"ethcore-logger 1.8.0",
|
"ethcore-logger 1.8.0",
|
||||||
|
"ethcore-network 1.8.0",
|
||||||
"ethcore-secretstore 1.0.0",
|
"ethcore-secretstore 1.0.0",
|
||||||
"ethcore-stratum 1.8.0",
|
"ethcore-stratum 1.8.0",
|
||||||
"ethcore-util 1.8.0",
|
"ethcore-util 1.8.0",
|
||||||
@ -1772,6 +1793,7 @@ dependencies = [
|
|||||||
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ipnetwork 0.12.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
||||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1925,7 +1947,6 @@ dependencies = [
|
|||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"ethstore 0.1.0",
|
"ethstore 0.1.0",
|
||||||
"ethsync 1.8.0",
|
"ethsync 1.8.0",
|
||||||
"evm 0.1.0",
|
|
||||||
"fetch 0.1.0",
|
"fetch 0.1.0",
|
||||||
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1954,6 +1975,7 @@ dependencies = [
|
|||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"vm 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2010,7 +2032,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-ui-precompiled"
|
name = "parity-ui-precompiled"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "git+https://github.com/paritytech/js-precompiled.git#fef524b2c679407d32a9ddef3af5dced97cdd3d0"
|
source = "git+https://github.com/paritytech/js-precompiled.git#4cde2187a26cc5d4588158034304c31b382fd5c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -3036,6 +3058,10 @@ dependencies = [
|
|||||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "using_queue"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8-ranges"
|
name = "utf8-ranges"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -3064,6 +3090,20 @@ dependencies = [
|
|||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vm"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"common-types 0.1.0",
|
||||||
|
"ethcore-util 1.8.0",
|
||||||
|
"ethjson 0.1.0",
|
||||||
|
"evmjit 1.8.0",
|
||||||
|
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rlp 0.2.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "void"
|
name = "void"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -3072,7 +3112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-utils"
|
name = "wasm-utils"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/paritytech/wasm-utils#fee06b6d5826c2dc1fc1aa183b0c2c75e3e140c3"
|
source = "git+https://github.com/paritytech/wasm-utils#9462bcc0680f0ec2c876abdf75bae981dd4344a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -3227,6 +3267,7 @@ dependencies = [
|
|||||||
"checksum igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356a0dc23a4fa0f8ce4777258085d00a01ea4923b2efd93538fc44bf5e1bda76"
|
"checksum igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356a0dc23a4fa0f8ce4777258085d00a01ea4923b2efd93538fc44bf5e1bda76"
|
||||||
"checksum integer-encoding 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a053c9c7dcb7db1f2aa012c37dc176c62e4cdf14898dee0eecc606de835b8acb"
|
"checksum integer-encoding 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a053c9c7dcb7db1f2aa012c37dc176c62e4cdf14898dee0eecc606de835b8acb"
|
||||||
"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
|
"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
|
||||||
|
"checksum ipnetwork 0.12.6 (registry+https://github.com/rust-lang/crates.io-index)" = "232e76922883005380e831068f731ef0305541c9f77b30df3a1635047b16f370"
|
||||||
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
|
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
|
||||||
"checksum itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d95557e7ba6b71377b0f2c3b3ae96c53f1b75a926a6901a500f557a370af730a"
|
"checksum itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d95557e7ba6b71377b0f2c3b3ae96c53f1b75a926a6901a500f557a370af730a"
|
||||||
"checksum itoa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91fd9dc2c587067de817fec4ad355e3818c3d893a78cab32a0a474c7a15bb8d5"
|
"checksum itoa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91fd9dc2c587067de817fec4ad355e3818c3d893a78cab32a0a474c7a15bb8d5"
|
||||||
|
@ -41,6 +41,7 @@ ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
|||||||
ethcore-light = { path = "ethcore/light" }
|
ethcore-light = { path = "ethcore/light" }
|
||||||
ethcore-logger = { path = "logger" }
|
ethcore-logger = { path = "logger" }
|
||||||
ethcore-stratum = { path = "stratum" }
|
ethcore-stratum = { path = "stratum" }
|
||||||
|
ethcore-network = { path = "util/network" }
|
||||||
ethkey = { path = "ethkey" }
|
ethkey = { path = "ethkey" }
|
||||||
rlp = { path = "util/rlp" }
|
rlp = { path = "util/rlp" }
|
||||||
rpc-cli = { path = "rpc_cli" }
|
rpc-cli = { path = "rpc_cli" }
|
||||||
@ -65,6 +66,7 @@ rustc_version = "0.2"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ethcore-ipc-tests = { path = "ipc/tests" }
|
ethcore-ipc-tests = { path = "ipc/tests" }
|
||||||
pretty_assertions = "0.1"
|
pretty_assertions = "0.1"
|
||||||
|
ipnetwork = "0.12.6"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = "0.2"
|
winapi = "0.2"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
### [Download latest release](https://github.com/paritytech/parity/releases)
|
### [Download latest release](https://github.com/paritytech/parity/releases)
|
||||||
|
|
||||||
[![build status](https://gitlab.parity.io/parity/parity/badges/master/build.svg)](https://gitlab.parity.io/parity/parity/commits/master) [![Coverage Status][coveralls-image]][coveralls-url] [![GPLv3][license-image]][license-url]
|
[![build status](https://gitlab.parity.io/parity/parity/badges/master/build.svg)](https://gitlab.parity.io/parity/parity/commits/master) [![Coverage Status][coveralls-image]][coveralls-url] [![GPLv3][license-image]][license-url] [![Snap Status](https://build.snapcraft.io/badge/paritytech/parity.svg)](https://build.snapcraft.io/user/paritytech/parity)
|
||||||
|
|
||||||
### Join the chat!
|
### Join the chat!
|
||||||
|
|
||||||
|
10
SECURITY.md
10
SECURITY.md
@ -42,3 +42,13 @@ ETBD1Q==
|
|||||||
=K9Qw
|
=K9Qw
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Important Legal Information:
|
||||||
|
|
||||||
|
Your submission might be eligible for a bug bounty. The bug bounty program is an experimental and discretionary rewards program for the Parity community to reward those who are helping to improve the Parity software. Rewards are at the sole discretion of Parity Technologies Ltd..
|
||||||
|
|
||||||
|
We are not able to issue rewards to individuals who are on sanctions lists or who are in countries on sanctions lists (e.g. North Korea, Iran, etc).
|
||||||
|
|
||||||
|
You are responsible for all taxes. All rewards are subject to applicable law.
|
||||||
|
|
||||||
|
Finally, your testing must not violate any law or compromise any data that is not yours.
|
||||||
|
@ -147,13 +147,7 @@ impl RestApiRouter {
|
|||||||
HealthInfo { status, message, details, }
|
HealthInfo { status, message, details, }
|
||||||
};
|
};
|
||||||
|
|
||||||
let status = if [&peers.status, &sync.status, &time.status].iter().any(|x| *x != &HealthStatus::Ok) {
|
response::as_json(StatusCode::Ok, &Health { peers, sync, time })
|
||||||
StatusCode::PreconditionFailed // HTTP 412
|
|
||||||
} else {
|
|
||||||
StatusCode::Ok // HTTP 200
|
|
||||||
};
|
|
||||||
|
|
||||||
response::as_json(status, &Health { peers, sync, time })
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let time = self.api.time.time_drift();
|
let time = self.api.time.time_drift();
|
||||||
|
@ -100,6 +100,10 @@ impl SimpleNtp {
|
|||||||
impl Ntp for SimpleNtp {
|
impl Ntp for SimpleNtp {
|
||||||
fn drift(&self) -> BoxFuture<Duration, Error> {
|
fn drift(&self) -> BoxFuture<Duration, Error> {
|
||||||
let address = self.address.clone();
|
let address = self.address.clone();
|
||||||
|
if &*address == "none" {
|
||||||
|
return futures::future::err(Error::Ntp("NTP server is not provided.".into())).boxed();
|
||||||
|
}
|
||||||
|
|
||||||
self.pool.spawn_fn(move || {
|
self.pool.spawn_fn(move || {
|
||||||
let packet = ntp::request(&*address)?;
|
let packet = ntp::request(&*address)?;
|
||||||
let dest_time = ::time::now_utc().to_timespec();
|
let dest_time = ::time::now_utc().to_timespec();
|
||||||
@ -114,7 +118,9 @@ impl Ntp for SimpleNtp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_RESULTS: usize = 4;
|
// NOTE In a positive scenario first results will be seen after:
|
||||||
|
// MAX_RESULTS * UPDATE_TIMEOUT_OK_SECS seconds.
|
||||||
|
const MAX_RESULTS: usize = 7;
|
||||||
const UPDATE_TIMEOUT_OK_SECS: u64 = 30;
|
const UPDATE_TIMEOUT_OK_SECS: u64 = 30;
|
||||||
const UPDATE_TIMEOUT_ERR_SECS: u64 = 2;
|
const UPDATE_TIMEOUT_ERR_SECS: u64 = 2;
|
||||||
|
|
||||||
@ -225,7 +231,7 @@ mod tests {
|
|||||||
|
|
||||||
fn time_checker() -> TimeChecker<FakeNtp> {
|
fn time_checker() -> TimeChecker<FakeNtp> {
|
||||||
let last_result = Arc::new(RwLock::new(
|
let last_result = Arc::new(RwLock::new(
|
||||||
(Instant::now(), vec![Err(Error::Ntp("NTP server unavailable.".into()))].into())
|
(Instant::now(), vec![Err(Error::Ntp("NTP server unavailable".into()))].into())
|
||||||
));
|
));
|
||||||
|
|
||||||
TimeChecker {
|
TimeChecker {
|
||||||
|
@ -123,7 +123,9 @@ impl Light {
|
|||||||
}
|
}
|
||||||
let num_nodes = cache_size / NODE_BYTES;
|
let num_nodes = cache_size / NODE_BYTES;
|
||||||
let mut nodes: Vec<Node> = Vec::with_capacity(num_nodes);
|
let mut nodes: Vec<Node> = Vec::with_capacity(num_nodes);
|
||||||
nodes.resize(num_nodes, unsafe { mem::uninitialized() });
|
|
||||||
|
unsafe { nodes.set_len(num_nodes) };
|
||||||
|
|
||||||
let buf = unsafe { slice::from_raw_parts_mut(nodes.as_mut_ptr() as *mut u8, cache_size) };
|
let buf = unsafe { slice::from_raw_parts_mut(nodes.as_mut_ptr() as *mut u8, cache_size) };
|
||||||
file.read_exact(buf)?;
|
file.read_exact(buf)?;
|
||||||
Ok(Light {
|
Ok(Light {
|
||||||
@ -208,17 +210,20 @@ pub fn slow_get_seedhash(block_number: u64) -> H256 {
|
|||||||
SeedHashCompute::resume_compute_seedhash([0u8; 32], 0, block_number / ETHASH_EPOCH_LENGTH)
|
SeedHashCompute::resume_compute_seedhash([0u8; 32], 0, block_number / ETHASH_EPOCH_LENGTH)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn fnv_hash(x: u32, y: u32) -> u32 {
|
fn fnv_hash(x: u32, y: u32) -> u32 {
|
||||||
return x.wrapping_mul(FNV_PRIME) ^ y;
|
return x.wrapping_mul(FNV_PRIME) ^ y;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn sha3_512(input: &[u8], output: &mut [u8]) {
|
fn sha3_512(input: &[u8], output: &mut [u8]) {
|
||||||
unsafe { sha3::sha3_512(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) };
|
unsafe { sha3::sha3_512(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
fn sha3_512_inplace(input: &mut [u8]) {
|
||||||
|
// This is safe since `sha3_*` uses an internal buffer and copies the result to the output. This
|
||||||
|
// means that we can reuse the input buffer for both input and output.
|
||||||
|
unsafe { sha3::sha3_512(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()) };
|
||||||
|
}
|
||||||
|
|
||||||
fn get_cache_size(block_number: u64) -> usize {
|
fn get_cache_size(block_number: u64) -> usize {
|
||||||
let mut sz: u64 = CACHE_BYTES_INIT + CACHE_BYTES_GROWTH * (block_number / ETHASH_EPOCH_LENGTH);
|
let mut sz: u64 = CACHE_BYTES_INIT + CACHE_BYTES_GROWTH * (block_number / ETHASH_EPOCH_LENGTH);
|
||||||
sz = sz - NODE_BYTES as u64;
|
sz = sz - NODE_BYTES as u64;
|
||||||
@ -228,7 +233,6 @@ fn get_cache_size(block_number: u64) -> usize {
|
|||||||
sz as usize
|
sz as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_data_size(block_number: u64) -> usize {
|
fn get_data_size(block_number: u64) -> usize {
|
||||||
let mut sz: u64 = DATASET_BYTES_INIT + DATASET_BYTES_GROWTH * (block_number / ETHASH_EPOCH_LENGTH);
|
let mut sz: u64 = DATASET_BYTES_INIT + DATASET_BYTES_GROWTH * (block_number / ETHASH_EPOCH_LENGTH);
|
||||||
sz = sz - ETHASH_MIX_BYTES as u64;
|
sz = sz - ETHASH_MIX_BYTES as u64;
|
||||||
@ -238,7 +242,6 @@ fn get_data_size(block_number: u64) -> usize {
|
|||||||
sz as usize
|
sz as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Difficulty quick check for POW preverification
|
/// Difficulty quick check for POW preverification
|
||||||
///
|
///
|
||||||
/// `header_hash` The hash of the header
|
/// `header_hash` The hash of the header
|
||||||
@ -246,18 +249,28 @@ fn get_data_size(block_number: u64) -> usize {
|
|||||||
/// `mix_hash` The mix digest hash
|
/// `mix_hash` The mix digest hash
|
||||||
/// Boundary recovered from mix hash
|
/// Boundary recovered from mix hash
|
||||||
pub fn quick_get_difficulty(header_hash: &H256, nonce: u64, mix_hash: &H256) -> H256 {
|
pub fn quick_get_difficulty(header_hash: &H256, nonce: u64, mix_hash: &H256) -> H256 {
|
||||||
let mut buf = [0u8; 64 + 32];
|
unsafe {
|
||||||
unsafe { ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32) };
|
// This is safe - the `sha3_512` call below reads the first 40 bytes (which we explicitly set
|
||||||
unsafe { ptr::copy_nonoverlapping(mem::transmute(&nonce), buf[32..].as_mut_ptr(), 8) };
|
// with two `copy_nonoverlapping` calls) but writes the first 64, and then we explicitly write
|
||||||
|
// the next 32 bytes before we read the whole thing with `sha3_256`.
|
||||||
|
//
|
||||||
|
// This cannot be elided by the compiler as it doesn't know the implementation of
|
||||||
|
// `sha3_512`.
|
||||||
|
let mut buf: [u8; 64 + 32] = mem::uninitialized();
|
||||||
|
|
||||||
unsafe { sha3::sha3_512(buf.as_mut_ptr(), 64, buf.as_ptr(), 40) };
|
ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32);
|
||||||
unsafe { ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32) };
|
ptr::copy_nonoverlapping(mem::transmute(&nonce), buf[32..].as_mut_ptr(), 8);
|
||||||
|
|
||||||
|
sha3::sha3_512(buf.as_mut_ptr(), 64, buf.as_ptr(), 40);
|
||||||
|
ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32);
|
||||||
|
|
||||||
|
// This is initialized in `sha3_256`
|
||||||
|
let mut hash: [u8; 32] = mem::uninitialized();
|
||||||
|
sha3::sha3_256(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len());
|
||||||
|
|
||||||
let mut hash = [0u8; 32];
|
|
||||||
unsafe { sha3::sha3_256(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len()) };
|
|
||||||
hash.as_mut_ptr();
|
|
||||||
hash
|
hash
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculate the light client data
|
/// Calculate the light client data
|
||||||
/// `light` - The light client handler
|
/// `light` - The light client handler
|
||||||
@ -269,39 +282,97 @@ pub fn light_compute(light: &Light, header_hash: &H256, nonce: u64) -> ProofOfWo
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) -> ProofOfWork {
|
fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) -> ProofOfWork {
|
||||||
|
macro_rules! make_const_array {
|
||||||
|
($n:expr, $value:expr) => {{
|
||||||
|
// We use explicit lifetimes to ensure that val's borrow is invalidated until the
|
||||||
|
// transmuted val dies.
|
||||||
|
unsafe fn make_const_array<'a, T, U>(val: &'a mut [T]) -> &'a mut [U; $n] {
|
||||||
|
use ::std::mem;
|
||||||
|
|
||||||
|
debug_assert_eq!(val.len() * mem::size_of::<T>(), $n * mem::size_of::<U>());
|
||||||
|
mem::transmute(val.as_mut_ptr())
|
||||||
|
}
|
||||||
|
|
||||||
|
make_const_array($value)
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct MixBuf {
|
||||||
|
half_mix: Node,
|
||||||
|
compress_bytes: [u8; MIX_WORDS],
|
||||||
|
};
|
||||||
|
|
||||||
if full_size % MIX_WORDS != 0 {
|
if full_size % MIX_WORDS != 0 {
|
||||||
panic!("Unaligned full size");
|
panic!("Unaligned full size");
|
||||||
}
|
}
|
||||||
// pack hash and nonce together into first 40 bytes of s_mix
|
|
||||||
let mut s_mix: [Node; MIX_NODES + 1] = [Node::default(), Node::default(), Node::default()];
|
// You may be asking yourself: what in the name of Crypto Jesus is going on here? So: we need
|
||||||
unsafe { ptr::copy_nonoverlapping(header_hash.as_ptr(), s_mix.get_unchecked_mut(0).bytes.as_mut_ptr(), 32) };
|
// `half_mix` and `compress_bytes` in a single array later down in the code (we hash them
|
||||||
unsafe { ptr::copy_nonoverlapping(mem::transmute(&nonce), s_mix.get_unchecked_mut(0).bytes[32..].as_mut_ptr(), 8) };
|
// together to create `value`) so that we can hash the full array. However, we do a bunch of
|
||||||
|
// reading and writing to these variables first. We originally allocated two arrays and then
|
||||||
|
// stuck them together with `ptr::copy_nonoverlapping` at the end, but this method is
|
||||||
|
// _significantly_ faster - by my benchmarks, a consistent 3-5%. This is the most ridiculous
|
||||||
|
// optimization I have ever done and I am so sorry. I can only chalk it up to cache locality
|
||||||
|
// improvements, since I can't imagine that 3-5% of our runtime is taken up by catting two
|
||||||
|
// arrays together.
|
||||||
|
let mut buf: MixBuf = MixBuf {
|
||||||
|
half_mix: unsafe {
|
||||||
|
// Pack `header_hash` and `nonce` together
|
||||||
|
// We explicitly write the first 40 bytes, leaving the last 24 as uninitialized. Then
|
||||||
|
// `sha3_512` reads the first 40 bytes (4th parameter) and overwrites the entire array,
|
||||||
|
// leaving it fully initialized.
|
||||||
|
let mut out: [u8; NODE_BYTES] = mem::uninitialized();
|
||||||
|
|
||||||
|
ptr::copy_nonoverlapping(
|
||||||
|
header_hash.as_ptr(),
|
||||||
|
out.as_mut_ptr(),
|
||||||
|
header_hash.len(),
|
||||||
|
);
|
||||||
|
ptr::copy_nonoverlapping(
|
||||||
|
mem::transmute(&nonce),
|
||||||
|
out[header_hash.len()..].as_mut_ptr(),
|
||||||
|
mem::size_of::<u64>(),
|
||||||
|
);
|
||||||
|
|
||||||
// compute sha3-512 hash and replicate across mix
|
// compute sha3-512 hash and replicate across mix
|
||||||
unsafe {
|
sha3::sha3_512(
|
||||||
sha3::sha3_512(s_mix.get_unchecked_mut(0).bytes.as_mut_ptr(), NODE_BYTES, s_mix.get_unchecked(0).bytes.as_ptr(), 40);
|
out.as_mut_ptr(),
|
||||||
let (f_mix, mut mix) = s_mix.split_at_mut(1);
|
NODE_BYTES,
|
||||||
for w in 0..MIX_WORDS {
|
out.as_ptr(),
|
||||||
*mix.get_unchecked_mut(0).as_words_mut().get_unchecked_mut(w) = *f_mix.get_unchecked(0).as_words().get_unchecked(w % NODE_WORDS);
|
header_hash.len() + mem::size_of::<u64>()
|
||||||
}
|
);
|
||||||
|
|
||||||
|
Node { bytes: out }
|
||||||
|
},
|
||||||
|
// This is fully initialized before being read, see `let mut compress = ...` below
|
||||||
|
compress_bytes: unsafe { mem::uninitialized() },
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut mix: [_; MIX_NODES] = [buf.half_mix.clone(), buf.half_mix.clone()];
|
||||||
|
|
||||||
let page_size = 4 * MIX_WORDS;
|
let page_size = 4 * MIX_WORDS;
|
||||||
let num_full_pages = (full_size / page_size) as u32;
|
let num_full_pages = (full_size / page_size) as u32;
|
||||||
let cache: &[Node] = &light.cache; // deref once for better performance
|
// deref once for better performance
|
||||||
|
let cache: &[Node] = &light.cache;
|
||||||
|
let first_val = buf.half_mix.as_words()[0];
|
||||||
|
|
||||||
debug_assert_eq!(ETHASH_ACCESSES, 64);
|
|
||||||
debug_assert_eq!(MIX_NODES, 2);
|
debug_assert_eq!(MIX_NODES, 2);
|
||||||
debug_assert_eq!(NODE_WORDS, 16);
|
debug_assert_eq!(NODE_WORDS, 16);
|
||||||
|
|
||||||
unroll! {
|
for i in 0..ETHASH_ACCESSES as u32 {
|
||||||
// ETHASH_ACCESSES
|
let index = {
|
||||||
for i_usize in 0..64 {
|
// This is trivially safe, but does not work on big-endian. The safety of this is
|
||||||
let i = i_usize as u32;
|
// asserted in debug builds (see the definition of `make_const_array!`).
|
||||||
|
let mix_words: &mut [u32; MIX_WORDS] = unsafe {
|
||||||
|
make_const_array!(MIX_WORDS, &mut mix)
|
||||||
|
};
|
||||||
|
|
||||||
let index = fnv_hash(
|
fnv_hash(
|
||||||
f_mix.get_unchecked(0).as_words().get_unchecked(0) ^ i,
|
first_val ^ i,
|
||||||
*mix.get_unchecked(0).as_words().get_unchecked(i as usize % MIX_WORDS)
|
mix_words[i as usize % MIX_WORDS]
|
||||||
) % num_full_pages;
|
) % num_full_pages
|
||||||
|
};
|
||||||
|
|
||||||
unroll! {
|
unroll! {
|
||||||
// MIX_NODES
|
// MIX_NODES
|
||||||
@ -314,74 +385,92 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
|||||||
unroll! {
|
unroll! {
|
||||||
// NODE_WORDS
|
// NODE_WORDS
|
||||||
for w in 0..16 {
|
for w in 0..16 {
|
||||||
*mix.get_unchecked_mut(n).as_words_mut().get_unchecked_mut(w) =
|
mix[n].as_words_mut()[w] =
|
||||||
fnv_hash(
|
fnv_hash(
|
||||||
*mix.get_unchecked(n).as_words().get_unchecked(w),
|
mix[n].as_words()[w],
|
||||||
*tmp_node.as_words().get_unchecked(w),
|
tmp_node.as_words()[w],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
let mix_words: [u32; MIX_WORDS] = unsafe { mem::transmute(mix) };
|
||||||
|
|
||||||
|
{
|
||||||
|
// This is an uninitialized buffer to begin with, but we iterate precisely `compress.len()`
|
||||||
|
// times and set each index, leaving the array fully initialized. THIS ONLY WORKS ON LITTLE-
|
||||||
|
// ENDIAN MACHINES. See a future PR to make this and the rest of the code work correctly on
|
||||||
|
// big-endian arches like mips.
|
||||||
|
let mut compress: &mut [u32; MIX_WORDS / 4] = unsafe {
|
||||||
|
make_const_array!(MIX_WORDS / 4, &mut buf.compress_bytes)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compress mix
|
||||||
debug_assert_eq!(MIX_WORDS / 4, 8);
|
debug_assert_eq!(MIX_WORDS / 4, 8);
|
||||||
|
|
||||||
// compress mix
|
|
||||||
unroll! {
|
unroll! {
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
let w = i * 4;
|
let w = i * 4;
|
||||||
let mut reduction = *mix.get_unchecked(0).as_words().get_unchecked(w + 0);
|
|
||||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ *mix.get_unchecked(0).as_words().get_unchecked(w + 1);
|
let mut reduction = mix_words[w + 0];
|
||||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ *mix.get_unchecked(0).as_words().get_unchecked(w + 2);
|
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1];
|
||||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ *mix.get_unchecked(0).as_words().get_unchecked(w + 3);
|
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2];
|
||||||
*mix.get_unchecked_mut(0).as_words_mut().get_unchecked_mut(i) = reduction;
|
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3];
|
||||||
|
compress[i] = reduction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut mix_hash = [0u8; 32];
|
let mix_hash = buf.compress_bytes;
|
||||||
let mut buf = [0u8; 32 + 64];
|
|
||||||
ptr::copy_nonoverlapping(f_mix.get_unchecked_mut(0).bytes.as_ptr(), buf.as_mut_ptr(), 64);
|
let value: H256 = unsafe {
|
||||||
ptr::copy_nonoverlapping(mix.get_unchecked_mut(0).bytes.as_ptr(), buf[64..].as_mut_ptr(), 32);
|
// We can interpret the buffer as an array of `u8`s, since it's `repr(C)`.
|
||||||
ptr::copy_nonoverlapping(mix.get_unchecked_mut(0).bytes.as_ptr(), mix_hash.as_mut_ptr(), 32);
|
let read_ptr: *const u8 = mem::transmute(&buf);
|
||||||
let mut value: H256 = [0u8; 32];
|
// We overwrite the second half since `sha3_256` has an internal buffer and so allows
|
||||||
sha3::sha3_256(value.as_mut_ptr(), value.len(), buf.as_ptr(), buf.len());
|
// overlapping arrays as input.
|
||||||
|
let write_ptr: *mut u8 = mem::transmute(&mut buf.compress_bytes);
|
||||||
|
sha3::sha3_256(
|
||||||
|
write_ptr,
|
||||||
|
buf.compress_bytes.len(),
|
||||||
|
read_ptr,
|
||||||
|
buf.half_mix.bytes.len() + buf.compress_bytes.len(),
|
||||||
|
);
|
||||||
|
buf.compress_bytes
|
||||||
|
};
|
||||||
|
|
||||||
ProofOfWork {
|
ProofOfWork {
|
||||||
mix_hash: mix_hash,
|
mix_hash: mix_hash,
|
||||||
value: value,
|
value: value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
|
fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
|
||||||
unsafe {
|
|
||||||
let num_parent_nodes = cache.len();
|
let num_parent_nodes = cache.len();
|
||||||
let init = cache.get_unchecked(node_index as usize % num_parent_nodes);
|
let mut ret = cache[node_index as usize % num_parent_nodes].clone();
|
||||||
let mut ret = init.clone();
|
ret.as_words_mut()[0] ^= node_index;
|
||||||
*ret.as_words_mut().get_unchecked_mut(0) ^= node_index;
|
|
||||||
sha3::sha3_512(ret.bytes.as_mut_ptr(), ret.bytes.len(), ret.bytes.as_ptr(), ret.bytes.len());
|
sha3_512_inplace(&mut ret.bytes);
|
||||||
|
|
||||||
debug_assert_eq!(NODE_WORDS, 16);
|
debug_assert_eq!(NODE_WORDS, 16);
|
||||||
for i in 0..ETHASH_DATASET_PARENTS as u32 {
|
for i in 0..ETHASH_DATASET_PARENTS as u32 {
|
||||||
let parent_index = fnv_hash(node_index ^ i, *ret.as_words().get_unchecked(i as usize % NODE_WORDS)) % num_parent_nodes as u32;
|
let parent_index = fnv_hash(
|
||||||
let parent = cache.get_unchecked(parent_index as usize);
|
node_index ^ i,
|
||||||
|
ret.as_words()[i as usize % NODE_WORDS],
|
||||||
|
) % num_parent_nodes as u32;
|
||||||
|
let parent = &cache[parent_index as usize];
|
||||||
|
|
||||||
unroll! {
|
unroll! {
|
||||||
for w in 0..16 {
|
for w in 0..16 {
|
||||||
*ret.as_words_mut().get_unchecked_mut(w) =
|
ret.as_words_mut()[w] = fnv_hash(ret.as_words()[w], parent.as_words()[w]);
|
||||||
fnv_hash(
|
|
||||||
*ret.as_words().get_unchecked(w),
|
|
||||||
*parent.as_words().get_unchecked(w)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sha3::sha3_512(ret.bytes.as_mut_ptr(), ret.bytes.len(), ret.bytes.as_ptr(), ret.bytes.len());
|
sha3_512_inplace(&mut ret.bytes);
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn light_new<T: AsRef<Path>>(cache_dir: T, block_number: u64) -> Light {
|
fn light_new<T: AsRef<Path>>(cache_dir: T, block_number: u64) -> Light {
|
||||||
let seed_compute = SeedHashCompute::new();
|
let seed_compute = SeedHashCompute::new();
|
||||||
@ -391,9 +480,11 @@ fn light_new<T: AsRef<Path>>(cache_dir: T, block_number: u64) -> Light {
|
|||||||
assert!(cache_size % NODE_BYTES == 0, "Unaligned cache size");
|
assert!(cache_size % NODE_BYTES == 0, "Unaligned cache size");
|
||||||
let num_nodes = cache_size / NODE_BYTES;
|
let num_nodes = cache_size / NODE_BYTES;
|
||||||
|
|
||||||
let mut nodes = Vec::with_capacity(num_nodes);
|
let mut nodes: Vec<Node> = Vec::with_capacity(num_nodes);
|
||||||
nodes.resize(num_nodes, Node::default());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// Use uninit instead of unnecessarily writing `size_of::<Node>() * num_nodes` 0s
|
||||||
|
nodes.set_len(num_nodes);
|
||||||
|
|
||||||
sha3_512(&seedhash[0..32], &mut nodes.get_unchecked_mut(0).bytes);
|
sha3_512(&seedhash[0..32], &mut nodes.get_unchecked_mut(0).bytes);
|
||||||
for i in 1..num_nodes {
|
for i in 1..num_nodes {
|
||||||
sha3::sha3_512(nodes.get_unchecked_mut(i).bytes.as_mut_ptr(), NODE_BYTES, nodes.get_unchecked(i - 1).bytes.as_ptr(), NODE_BYTES);
|
sha3::sha3_512(nodes.get_unchecked_mut(i).bytes.as_mut_ptr(), NODE_BYTES, nodes.get_unchecked(i - 1).bytes.as_ptr(), NODE_BYTES);
|
||||||
|
@ -143,9 +143,11 @@ mod benchmarks {
|
|||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_light_compute(b: &mut Bencher) {
|
fn bench_light_compute(b: &mut Bencher) {
|
||||||
|
use ::std::env;
|
||||||
|
|
||||||
let hash = [0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe, 0xe4, 0x0a, 0xb3, 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f, 0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, 0x05, 0x52, 0x7d, 0x72];
|
let hash = [0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe, 0xe4, 0x0a, 0xb3, 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f, 0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, 0x05, 0x52, 0x7d, 0x72];
|
||||||
let nonce = 0xd7b3ac70a301a249;
|
let nonce = 0xd7b3ac70a301a249;
|
||||||
let light = Light::new(486382);
|
let light = Light::new(env::temp_dir(), 486382);
|
||||||
|
|
||||||
b.iter(|| light_compute(&light, &hash, nonce));
|
b.iter(|| light_compute(&light, &hash, nonce));
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,8 @@ semver = "0.6"
|
|||||||
stats = { path = "../util/stats" }
|
stats = { path = "../util/stats" }
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
transient-hashmap = "0.4"
|
transient-hashmap = "0.4"
|
||||||
|
vm = { path = "vm" }
|
||||||
|
wasm = { path = "wasm" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
native-contracts = { path = "native_contracts", features = ["test_contracts"] }
|
native-contracts = { path = "native_contracts", features = ["test_contracts"] }
|
||||||
|
@ -13,11 +13,11 @@ ethjson = { path = "../../json" }
|
|||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
rlp = { path = "../../util/rlp" }
|
rlp = { path = "../../util/rlp" }
|
||||||
|
vm = { path = "../vm" }
|
||||||
parity-wasm = "0.12"
|
parity-wasm = "0.12"
|
||||||
ethcore-logger = { path = "../../logger" }
|
ethcore-logger = { path = "../../logger" }
|
||||||
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
|
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rustc-hex = "1.0"
|
rustc-hex = "1.0"
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ extern crate test;
|
|||||||
use self::test::{Bencher, black_box};
|
use self::test::{Bencher, black_box};
|
||||||
|
|
||||||
use util::*;
|
use util::*;
|
||||||
use evm::action_params::ActionParams;
|
use vm::ActionParams;
|
||||||
use evm::{self, Factory, VMType};
|
use evm::{self, Factory, VMType};
|
||||||
use evm::tests::FakeExt;
|
use evm::tests::FakeExt;
|
||||||
|
|
||||||
|
@ -17,142 +17,8 @@
|
|||||||
//! Evm interface.
|
//! Evm interface.
|
||||||
|
|
||||||
use std::{ops, cmp, fmt};
|
use std::{ops, cmp, fmt};
|
||||||
use util::{U128, U256, U512, trie};
|
use util::{U128, U256, U512};
|
||||||
use action_params::ActionParams;
|
use vm::{Ext, Result, ReturnData, GasLeft, Error};
|
||||||
use {Ext};
|
|
||||||
|
|
||||||
use super::wasm;
|
|
||||||
|
|
||||||
/// Evm errors.
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum Error {
|
|
||||||
/// `OutOfGas` is returned when transaction execution runs out of gas.
|
|
||||||
/// The state should be reverted to the state from before the
|
|
||||||
/// transaction execution. But it does not mean that transaction
|
|
||||||
/// was invalid. Balance still should be transfered and nonce
|
|
||||||
/// should be increased.
|
|
||||||
OutOfGas,
|
|
||||||
/// `BadJumpDestination` is returned when execution tried to move
|
|
||||||
/// to position that wasn't marked with JUMPDEST instruction
|
|
||||||
BadJumpDestination {
|
|
||||||
/// Position the code tried to jump to.
|
|
||||||
destination: usize
|
|
||||||
},
|
|
||||||
/// `BadInstructions` is returned when given instruction is not supported
|
|
||||||
BadInstruction {
|
|
||||||
/// Unrecognized opcode
|
|
||||||
instruction: u8,
|
|
||||||
},
|
|
||||||
/// `StackUnderflow` when there is not enough stack elements to execute instruction
|
|
||||||
StackUnderflow {
|
|
||||||
/// Invoked instruction
|
|
||||||
instruction: &'static str,
|
|
||||||
/// How many stack elements was requested by instruction
|
|
||||||
wanted: usize,
|
|
||||||
/// How many elements were on stack
|
|
||||||
on_stack: usize
|
|
||||||
},
|
|
||||||
/// When execution would exceed defined Stack Limit
|
|
||||||
OutOfStack {
|
|
||||||
/// Invoked instruction
|
|
||||||
instruction: &'static str,
|
|
||||||
/// How many stack elements instruction wanted to push
|
|
||||||
wanted: usize,
|
|
||||||
/// What was the stack limit
|
|
||||||
limit: usize
|
|
||||||
},
|
|
||||||
/// Built-in contract failed on given input
|
|
||||||
BuiltIn(&'static str),
|
|
||||||
/// When execution tries to modify the state in static context
|
|
||||||
MutableCallInStaticContext,
|
|
||||||
/// Likely to cause consensus issues.
|
|
||||||
Internal(String),
|
|
||||||
/// Wasm runtime error
|
|
||||||
Wasm(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Box<trie::TrieError>> for Error {
|
|
||||||
fn from(err: Box<trie::TrieError>) -> Self {
|
|
||||||
Error::Internal(format!("Internal error: {}", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<wasm::RuntimeError> for Error {
|
|
||||||
fn from(err: wasm::RuntimeError) -> Self {
|
|
||||||
Error::Wasm(format!("Runtime error: {:?}", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
use self::Error::*;
|
|
||||||
match *self {
|
|
||||||
OutOfGas => write!(f, "Out of gas"),
|
|
||||||
BadJumpDestination { destination } => write!(f, "Bad jump destination {:x}", destination),
|
|
||||||
BadInstruction { instruction } => write!(f, "Bad instruction {:x}", instruction),
|
|
||||||
StackUnderflow { instruction, wanted, on_stack } => write!(f, "Stack underflow {} {}/{}", instruction, wanted, on_stack),
|
|
||||||
OutOfStack { instruction, wanted, limit } => write!(f, "Out of stack {} {}/{}", instruction, wanted, limit),
|
|
||||||
BuiltIn(name) => write!(f, "Built-in failed: {}", name),
|
|
||||||
Internal(ref msg) => write!(f, "Internal error: {}", msg),
|
|
||||||
MutableCallInStaticContext => write!(f, "Mutable call in static context"),
|
|
||||||
Wasm(ref msg) => write!(f, "Internal error: {}", msg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A specialized version of Result over EVM errors.
|
|
||||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
|
||||||
|
|
||||||
/// Return data buffer. Holds memory from a previous call and a slice into that memory.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ReturnData {
|
|
||||||
mem: Vec<u8>,
|
|
||||||
offset: usize,
|
|
||||||
size: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::ops::Deref for ReturnData {
|
|
||||||
type Target = [u8];
|
|
||||||
fn deref(&self) -> &[u8] {
|
|
||||||
&self.mem[self.offset..self.offset + self.size]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ReturnData {
|
|
||||||
/// Create empty `ReturnData`.
|
|
||||||
pub fn empty() -> Self {
|
|
||||||
ReturnData {
|
|
||||||
mem: Vec::new(),
|
|
||||||
offset: 0,
|
|
||||||
size: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Create `ReturnData` from give buffer and slice.
|
|
||||||
pub fn new(mem: Vec<u8>, offset: usize, size: usize) -> Self {
|
|
||||||
ReturnData {
|
|
||||||
mem: mem,
|
|
||||||
offset: offset,
|
|
||||||
size: size,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gas Left: either it is a known value, or it needs to be computed by processing
|
|
||||||
/// a return instruction.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum GasLeft {
|
|
||||||
/// Known gas left
|
|
||||||
Known(U256),
|
|
||||||
/// Return or Revert instruction must be processed.
|
|
||||||
NeedsReturn {
|
|
||||||
/// Amount of gas left.
|
|
||||||
gas_left: U256,
|
|
||||||
/// Return data buffer.
|
|
||||||
data: ReturnData,
|
|
||||||
/// Apply or revert state changes on revert.
|
|
||||||
apply_state: bool
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finalization result. Gas Left: either it is a known value, or it needs to be computed by processing
|
/// Finalization result. Gas Left: either it is a known value, or it needs to be computed by processing
|
||||||
/// a return instruction.
|
/// a return instruction.
|
||||||
@ -281,15 +147,6 @@ impl CostType for usize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evm interface
|
|
||||||
pub trait Evm {
|
|
||||||
/// This function should be used to execute transaction.
|
|
||||||
///
|
|
||||||
/// It returns either an error, a known amount of gas left, or parameters to be used
|
|
||||||
/// to compute the final gas left.
|
|
||||||
fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result<GasLeft>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use util::U256;
|
use util::U256;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! Evm factory.
|
//! Evm factory.
|
||||||
//!
|
//!
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use evm::Evm;
|
use vm::Vm;
|
||||||
use util::U256;
|
use util::U256;
|
||||||
use super::interpreter::SharedCache;
|
use super::interpreter::SharedCache;
|
||||||
use super::vmtype::VMType;
|
use super::vmtype::VMType;
|
||||||
@ -33,7 +33,7 @@ impl Factory {
|
|||||||
/// Create fresh instance of VM
|
/// Create fresh instance of VM
|
||||||
/// Might choose implementation depending on supplied gas.
|
/// Might choose implementation depending on supplied gas.
|
||||||
#[cfg(feature = "jit")]
|
#[cfg(feature = "jit")]
|
||||||
pub fn create(&self, gas: U256) -> Box<Evm> {
|
pub fn create(&self, gas: U256) -> Box<Vm> {
|
||||||
match self.evm {
|
match self.evm {
|
||||||
VMType::Jit => {
|
VMType::Jit => {
|
||||||
Box::new(super::jit::JitEvm::default())
|
Box::new(super::jit::JitEvm::default())
|
||||||
@ -49,7 +49,7 @@ impl Factory {
|
|||||||
/// Create fresh instance of VM
|
/// Create fresh instance of VM
|
||||||
/// Might choose implementation depending on supplied gas.
|
/// Might choose implementation depending on supplied gas.
|
||||||
#[cfg(not(feature = "jit"))]
|
#[cfg(not(feature = "jit"))]
|
||||||
pub fn create(&self, gas: U256) -> Box<Evm> {
|
pub fn create(&self, gas: U256) -> Box<Vm> {
|
||||||
match self.evm {
|
match self.evm {
|
||||||
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
||||||
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
|
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
|
||||||
|
@ -17,15 +17,15 @@
|
|||||||
use util::*;
|
use util::*;
|
||||||
use super::u256_to_address;
|
use super::u256_to_address;
|
||||||
|
|
||||||
use {evm, ext};
|
use {evm, vm};
|
||||||
use instructions::{self, Instruction, InstructionInfo};
|
use instructions::{self, Instruction, InstructionInfo};
|
||||||
use interpreter::stack::Stack;
|
use interpreter::stack::Stack;
|
||||||
use schedule::Schedule;
|
use vm::Schedule;
|
||||||
|
|
||||||
macro_rules! overflowing {
|
macro_rules! overflowing {
|
||||||
($x: expr) => {{
|
($x: expr) => {{
|
||||||
let (v, overflow) = $x;
|
let (v, overflow) = $x;
|
||||||
if overflow { return Err(evm::Error::OutOfGas); }
|
if overflow { return Err(vm::Error::OutOfGas); }
|
||||||
v
|
v
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -59,16 +59,16 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_gas(&self, gas_cost: &Gas) -> evm::Result<()> {
|
pub fn verify_gas(&self, gas_cost: &Gas) -> vm::Result<()> {
|
||||||
match &self.current_gas < gas_cost {
|
match &self.current_gas < gas_cost {
|
||||||
true => Err(evm::Error::OutOfGas),
|
true => Err(vm::Error::OutOfGas),
|
||||||
false => Ok(())
|
false => Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How much gas is provided to a CALL/CREATE, given that we need to deduct `needed` for this operation
|
/// How much gas is provided to a CALL/CREATE, given that we need to deduct `needed` for this operation
|
||||||
/// and that we `requested` some.
|
/// and that we `requested` some.
|
||||||
pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option<U256>) -> evm::Result<Gas> {
|
pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option<U256>) -> vm::Result<Gas> {
|
||||||
// Try converting requested gas to `Gas` (`U256/u64`)
|
// Try converting requested gas to `Gas` (`U256/u64`)
|
||||||
// but in EIP150 even if we request more we should never fail from OOG
|
// but in EIP150 even if we request more we should never fail from OOG
|
||||||
let requested = requested.map(Gas::from_u256);
|
let requested = requested.map(Gas::from_u256);
|
||||||
@ -107,12 +107,12 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
|||||||
/// it will be the amount of gas that the current context provides to the child context.
|
/// it will be the amount of gas that the current context provides to the child context.
|
||||||
pub fn requirements(
|
pub fn requirements(
|
||||||
&mut self,
|
&mut self,
|
||||||
ext: &ext::Ext,
|
ext: &vm::Ext,
|
||||||
instruction: Instruction,
|
instruction: Instruction,
|
||||||
info: &InstructionInfo,
|
info: &InstructionInfo,
|
||||||
stack: &Stack<U256>,
|
stack: &Stack<U256>,
|
||||||
current_mem_size: usize,
|
current_mem_size: usize,
|
||||||
) -> evm::Result<InstructionRequirements<Gas>> {
|
) -> vm::Result<InstructionRequirements<Gas>> {
|
||||||
let schedule = ext.schedule();
|
let schedule = ext.schedule();
|
||||||
let tier = instructions::get_tier_idx(info.tier);
|
let tier = instructions::get_tier_idx(info.tier);
|
||||||
let default_gas = Gas::from(schedule.tier_step_gas[tier]);
|
let default_gas = Gas::from(schedule.tier_step_gas[tier]);
|
||||||
@ -291,7 +291,7 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mem_gas_cost(&self, schedule: &Schedule, current_mem_size: usize, mem_size: &Gas) -> evm::Result<(Gas, Gas, usize)> {
|
fn mem_gas_cost(&self, schedule: &Schedule, current_mem_size: usize, mem_size: &Gas) -> vm::Result<(Gas, Gas, usize)> {
|
||||||
let gas_for_mem = |mem_size: Gas| {
|
let gas_for_mem = |mem_size: Gas| {
|
||||||
let s = mem_size >> 5;
|
let s = mem_size >> 5;
|
||||||
// s * memory_gas + s * s / quad_coeff_div
|
// s * memory_gas + s * s / quad_coeff_div
|
||||||
@ -319,12 +319,12 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
|||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mem_needed_const<Gas: evm::CostType>(mem: &U256, add: usize) -> evm::Result<Gas> {
|
fn mem_needed_const<Gas: evm::CostType>(mem: &U256, add: usize) -> vm::Result<Gas> {
|
||||||
Gas::from_u256(overflowing!(mem.overflowing_add(U256::from(add))))
|
Gas::from_u256(overflowing!(mem.overflowing_add(U256::from(add))))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mem_needed<Gas: evm::CostType>(offset: &U256, size: &U256) -> evm::Result<Gas> {
|
fn mem_needed<Gas: evm::CostType>(offset: &U256, size: &U256) -> vm::Result<Gas> {
|
||||||
if size.is_zero() {
|
if size.is_zero() {
|
||||||
return Ok(Gas::from(0));
|
return Ok(Gas::from(0));
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use util::U256;
|
use util::U256;
|
||||||
use {ReturnData};
|
use vm::ReturnData;
|
||||||
|
|
||||||
const MAX_RETURN_WASTE_BYTES: usize = 16384;
|
const MAX_RETURN_WASTE_BYTES: usize = 16384;
|
||||||
|
|
||||||
|
@ -23,17 +23,21 @@ mod stack;
|
|||||||
mod memory;
|
mod memory;
|
||||||
mod shared_cache;
|
mod shared_cache;
|
||||||
|
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use vm::{
|
||||||
|
self, ActionParams, ActionValue, CallType, MessageCallResult,
|
||||||
|
ContractCreateResult, CreateContractAddress, ReturnData, GasLeft
|
||||||
|
};
|
||||||
|
|
||||||
|
use evm::CostType;
|
||||||
|
use instructions::{self, Instruction, InstructionInfo};
|
||||||
|
|
||||||
use self::gasometer::Gasometer;
|
use self::gasometer::Gasometer;
|
||||||
use self::stack::{Stack, VecStack};
|
use self::stack::{Stack, VecStack};
|
||||||
use self::memory::Memory;
|
use self::memory::Memory;
|
||||||
pub use self::shared_cache::SharedCache;
|
pub use self::shared_cache::SharedCache;
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use action_params::{ActionParams, ActionValue};
|
|
||||||
use call_type::CallType;
|
|
||||||
use instructions::{self, Instruction, InstructionInfo};
|
|
||||||
use evm::{self, GasLeft, CostType, ReturnData};
|
|
||||||
use ext::{self, MessageCallResult, ContractCreateResult, CreateContractAddress};
|
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
|
|
||||||
use util::*;
|
use util::*;
|
||||||
@ -107,8 +111,8 @@ pub struct Interpreter<Cost: CostType> {
|
|||||||
_type: PhantomData<Cost>,
|
_type: PhantomData<Cost>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Cost: CostType> evm::Evm for Interpreter<Cost> {
|
impl<Cost: CostType> vm::Vm for Interpreter<Cost> {
|
||||||
fn exec(&mut self, params: ActionParams, ext: &mut ext::Ext) -> evm::Result<GasLeft> {
|
fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
|
||||||
self.mem.clear();
|
self.mem.clear();
|
||||||
|
|
||||||
let mut informant = informant::EvmInformant::new(ext.depth());
|
let mut informant = informant::EvmInformant::new(ext.depth());
|
||||||
@ -205,7 +209,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_instruction(&self, ext: &ext::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> {
|
fn verify_instruction(&self, ext: &vm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> vm::Result<()> {
|
||||||
let schedule = ext.schedule();
|
let schedule = ext.schedule();
|
||||||
|
|
||||||
if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
|
if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
|
||||||
@ -214,25 +218,25 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) ||
|
((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) ||
|
||||||
(instruction == instructions::REVERT && !schedule.have_revert) {
|
(instruction == instructions::REVERT && !schedule.have_revert) {
|
||||||
|
|
||||||
return Err(evm::Error::BadInstruction {
|
return Err(vm::Error::BadInstruction {
|
||||||
instruction: instruction
|
instruction: instruction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.tier == instructions::GasPriceTier::Invalid {
|
if info.tier == instructions::GasPriceTier::Invalid {
|
||||||
return Err(evm::Error::BadInstruction {
|
return Err(vm::Error::BadInstruction {
|
||||||
instruction: instruction
|
instruction: instruction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if !stack.has(info.args) {
|
if !stack.has(info.args) {
|
||||||
Err(evm::Error::StackUnderflow {
|
Err(vm::Error::StackUnderflow {
|
||||||
instruction: info.name,
|
instruction: info.name,
|
||||||
wanted: info.args,
|
wanted: info.args,
|
||||||
on_stack: stack.size()
|
on_stack: stack.size()
|
||||||
})
|
})
|
||||||
} else if stack.size() - info.args + info.ret > schedule.stack_limit {
|
} else if stack.size() - info.args + info.ret > schedule.stack_limit {
|
||||||
Err(evm::Error::OutOfStack {
|
Err(vm::Error::OutOfStack {
|
||||||
instruction: info.name,
|
instruction: info.name,
|
||||||
wanted: info.ret - info.args,
|
wanted: info.ret - info.args,
|
||||||
limit: schedule.stack_limit
|
limit: schedule.stack_limit
|
||||||
@ -272,12 +276,12 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
gas: Cost,
|
gas: Cost,
|
||||||
params: &ActionParams,
|
params: &ActionParams,
|
||||||
ext: &mut ext::Ext,
|
ext: &mut vm::Ext,
|
||||||
instruction: Instruction,
|
instruction: Instruction,
|
||||||
code: &mut CodeReader,
|
code: &mut CodeReader,
|
||||||
stack: &mut Stack<U256>,
|
stack: &mut Stack<U256>,
|
||||||
provided: Option<Cost>
|
provided: Option<Cost>
|
||||||
) -> evm::Result<InstructionResult<Cost>> {
|
) -> vm::Result<InstructionResult<Cost>> {
|
||||||
match instruction {
|
match instruction {
|
||||||
instructions::JUMP => {
|
instructions::JUMP => {
|
||||||
let jump = stack.pop_back();
|
let jump = stack.pop_back();
|
||||||
@ -593,13 +597,13 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_jump(&self, jump_u: U256, valid_jump_destinations: &BitSet) -> evm::Result<usize> {
|
fn verify_jump(&self, jump_u: U256, valid_jump_destinations: &BitSet) -> vm::Result<usize> {
|
||||||
let jump = jump_u.low_u64() as usize;
|
let jump = jump_u.low_u64() as usize;
|
||||||
|
|
||||||
if valid_jump_destinations.contains(jump) && U256::from(jump) == jump_u {
|
if valid_jump_destinations.contains(jump) && U256::from(jump) == jump_u {
|
||||||
Ok(jump)
|
Ok(jump)
|
||||||
} else {
|
} else {
|
||||||
Err(evm::Error::BadJumpDestination {
|
Err(vm::Error::BadJumpDestination {
|
||||||
destination: jump
|
destination: jump
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -617,7 +621,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_stack_instruction(&self, instruction: Instruction, stack: &mut Stack<U256>) -> evm::Result<()> {
|
fn exec_stack_instruction(&self, instruction: Instruction, stack: &mut Stack<U256>) -> vm::Result<()> {
|
||||||
match instruction {
|
match instruction {
|
||||||
instructions::DUP1...instructions::DUP16 => {
|
instructions::DUP1...instructions::DUP16 => {
|
||||||
let position = instructions::get_dup_position(instruction);
|
let position = instructions::get_dup_position(instruction);
|
||||||
@ -822,7 +826,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(evm::Error::BadInstruction {
|
return Err(vm::Error::BadInstruction {
|
||||||
instruction: instruction
|
instruction: instruction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ use util::*;
|
|||||||
use evmjit;
|
use evmjit;
|
||||||
use evm::{self, GasLeft};
|
use evm::{self, GasLeft};
|
||||||
use evm::CallType;
|
use evm::CallType;
|
||||||
|
use vm::{self, Vm};
|
||||||
|
|
||||||
/// Should be used to convert jit types to ethcore
|
/// Should be used to convert jit types to ethcore
|
||||||
trait FromJit<T>: Sized {
|
trait FromJit<T>: Sized {
|
||||||
@ -318,7 +319,7 @@ pub struct JitEvm {
|
|||||||
context: Option<evmjit::ContextHandle>,
|
context: Option<evmjit::ContextHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl evm::Evm for JitEvm {
|
impl vm::Vm for JitEvm {
|
||||||
fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> {
|
fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> {
|
||||||
// Dirty hack. This is unsafe, but we interact with ffi, so it's justified.
|
// Dirty hack. This is unsafe, but we interact with ffi, so it's justified.
|
||||||
let ext_adapter: ExtAdapter<'static> = unsafe { ::std::mem::transmute(ExtAdapter::new(ext, params.address.clone())) };
|
let ext_adapter: ExtAdapter<'static> = unsafe { ::std::mem::transmute(ExtAdapter::new(ext, params.address.clone())) };
|
||||||
@ -370,8 +371,8 @@ impl evm::Evm for JitEvm {
|
|||||||
ext.suicide(&Address::from_jit(&context.suicide_refund_address()));
|
ext.suicide(&Address::from_jit(&context.suicide_refund_address()));
|
||||||
Ok(GasLeft::Known(U256::from(context.gas_left())))
|
Ok(GasLeft::Known(U256::from(context.gas_left())))
|
||||||
},
|
},
|
||||||
evmjit::ReturnCode::OutOfGas => Err(evm::Error::OutOfGas),
|
evmjit::ReturnCode::OutOfGas => Err(vm::Error::OutOfGas),
|
||||||
_err => Err(evm::Error::Internal)
|
_err => Err(vm::Error::Internal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,11 @@ extern crate rlp;
|
|||||||
extern crate parity_wasm;
|
extern crate parity_wasm;
|
||||||
extern crate wasm_utils;
|
extern crate wasm_utils;
|
||||||
extern crate ethcore_logger;
|
extern crate ethcore_logger;
|
||||||
|
extern crate vm;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
#[cfg(feature = "jit")]
|
#[cfg(feature = "jit")]
|
||||||
@ -38,14 +38,8 @@ extern crate evmjit;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
|
|
||||||
pub mod action_params;
|
|
||||||
pub mod call_type;
|
|
||||||
pub mod env_info;
|
|
||||||
pub mod ext;
|
|
||||||
pub mod evm;
|
pub mod evm;
|
||||||
pub mod interpreter;
|
pub mod interpreter;
|
||||||
pub mod schedule;
|
|
||||||
pub mod wasm;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod factory;
|
pub mod factory;
|
||||||
@ -60,12 +54,12 @@ mod tests;
|
|||||||
#[cfg(all(feature="benches", test))]
|
#[cfg(all(feature="benches", test))]
|
||||||
mod benches;
|
mod benches;
|
||||||
|
|
||||||
pub use self::action_params::ActionParams;
|
pub use vm::{
|
||||||
pub use self::call_type::CallType;
|
Schedule, CleanDustMode, EnvInfo, CallType, ActionParams, Ext,
|
||||||
pub use self::env_info::EnvInfo;
|
ContractCreateResult, MessageCallResult, CreateContractAddress,
|
||||||
pub use self::evm::{Evm, Error, Finalize, FinalizationResult, GasLeft, Result, CostType, ReturnData};
|
GasLeft, ReturnData
|
||||||
pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress};
|
};
|
||||||
|
pub use self::evm::{Finalize, FinalizationResult, CostType};
|
||||||
pub use self::instructions::{InstructionInfo, INSTRUCTIONS, push_bytes};
|
pub use self::instructions::{InstructionInfo, INSTRUCTIONS, push_bytes};
|
||||||
pub use self::vmtype::VMType;
|
pub use self::vmtype::VMType;
|
||||||
pub use self::factory::Factory;
|
pub use self::factory::Factory;
|
||||||
pub use self::schedule::{Schedule, CleanDustMode};
|
|
||||||
|
@ -17,210 +17,11 @@
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use rustc_hex::FromHex;
|
use rustc_hex::FromHex;
|
||||||
use util::*;
|
use util::*;
|
||||||
use action_params::{ActionParams, ActionValue};
|
use vm::{self, ActionParams, ActionValue};
|
||||||
use env_info::EnvInfo;
|
use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize};
|
||||||
use call_type::CallType;
|
|
||||||
use schedule::Schedule;
|
|
||||||
use evm::{self, GasLeft, ReturnData};
|
|
||||||
use ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress};
|
|
||||||
use factory::Factory;
|
use factory::Factory;
|
||||||
use vmtype::VMType;
|
use vmtype::VMType;
|
||||||
|
|
||||||
pub struct FakeLogEntry {
|
|
||||||
topics: Vec<H256>,
|
|
||||||
data: Bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
|
||||||
pub enum FakeCallType {
|
|
||||||
Call, Create
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
|
||||||
pub struct FakeCall {
|
|
||||||
pub call_type: FakeCallType,
|
|
||||||
pub gas: U256,
|
|
||||||
pub sender_address: Option<Address>,
|
|
||||||
pub receive_address: Option<Address>,
|
|
||||||
pub value: Option<U256>,
|
|
||||||
pub data: Bytes,
|
|
||||||
pub code_address: Option<Address>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fake externalities test structure.
|
|
||||||
///
|
|
||||||
/// Can't do recursive calls.
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct FakeExt {
|
|
||||||
pub store: HashMap<H256, H256>,
|
|
||||||
pub suicides: HashSet<Address>,
|
|
||||||
pub calls: HashSet<FakeCall>,
|
|
||||||
sstore_clears: usize,
|
|
||||||
depth: usize,
|
|
||||||
blockhashes: HashMap<U256, H256>,
|
|
||||||
codes: HashMap<Address, Arc<Bytes>>,
|
|
||||||
logs: Vec<FakeLogEntry>,
|
|
||||||
info: EnvInfo,
|
|
||||||
schedule: Schedule,
|
|
||||||
balances: HashMap<Address, U256>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// similar to the normal `finalize` function, but ignoring NeedsReturn.
|
|
||||||
fn test_finalize(res: Result<GasLeft, evm::Error>) -> Result<U256, evm::Error> {
|
|
||||||
match res {
|
|
||||||
Ok(GasLeft::Known(gas)) => Ok(gas),
|
|
||||||
Ok(GasLeft::NeedsReturn{..}) => unimplemented!(), // since ret is unimplemented.
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FakeExt {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
FakeExt::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Schedule {
|
|
||||||
fn default() -> Self {
|
|
||||||
Schedule::new_frontier()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ext for FakeExt {
|
|
||||||
fn storage_at(&self, key: &H256) -> evm::Result<H256> {
|
|
||||||
Ok(self.store.get(key).unwrap_or(&H256::new()).clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> {
|
|
||||||
self.store.insert(key, value);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn exists(&self, address: &Address) -> evm::Result<bool> {
|
|
||||||
Ok(self.balances.contains_key(address))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn exists_and_not_null(&self, address: &Address) -> evm::Result<bool> {
|
|
||||||
Ok(self.balances.get(address).map_or(false, |b| !b.is_zero()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn origin_balance(&self) -> evm::Result<U256> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn balance(&self, address: &Address) -> evm::Result<U256> {
|
|
||||||
Ok(self.balances[address])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn blockhash(&mut self, number: &U256) -> H256 {
|
|
||||||
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
|
|
||||||
self.calls.insert(FakeCall {
|
|
||||||
call_type: FakeCallType::Create,
|
|
||||||
gas: *gas,
|
|
||||||
sender_address: None,
|
|
||||||
receive_address: None,
|
|
||||||
value: Some(*value),
|
|
||||||
data: code.to_vec(),
|
|
||||||
code_address: None
|
|
||||||
});
|
|
||||||
ContractCreateResult::Failed
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self,
|
|
||||||
gas: &U256,
|
|
||||||
sender_address: &Address,
|
|
||||||
receive_address: &Address,
|
|
||||||
value: Option<U256>,
|
|
||||||
data: &[u8],
|
|
||||||
code_address: &Address,
|
|
||||||
_output: &mut [u8],
|
|
||||||
_call_type: CallType
|
|
||||||
) -> MessageCallResult {
|
|
||||||
|
|
||||||
self.calls.insert(FakeCall {
|
|
||||||
call_type: FakeCallType::Call,
|
|
||||||
gas: *gas,
|
|
||||||
sender_address: Some(sender_address.clone()),
|
|
||||||
receive_address: Some(receive_address.clone()),
|
|
||||||
value: value,
|
|
||||||
data: data.to_vec(),
|
|
||||||
code_address: Some(code_address.clone())
|
|
||||||
});
|
|
||||||
MessageCallResult::Success(*gas, ReturnData::empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extcode(&self, address: &Address) -> evm::Result<Arc<Bytes>> {
|
|
||||||
Ok(self.codes.get(address).unwrap_or(&Arc::new(Bytes::new())).clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extcodesize(&self, address: &Address) -> evm::Result<usize> {
|
|
||||||
Ok(self.codes.get(address).map_or(0, |c| c.len()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> evm::Result<()> {
|
|
||||||
self.logs.push(FakeLogEntry {
|
|
||||||
topics: topics,
|
|
||||||
data: data.to_vec()
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ret(self, _gas: &U256, _data: &ReturnData) -> evm::Result<U256> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> {
|
|
||||||
self.suicides.insert(refund_address.clone());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn schedule(&self) -> &Schedule {
|
|
||||||
&self.schedule
|
|
||||||
}
|
|
||||||
|
|
||||||
fn env_info(&self) -> &EnvInfo {
|
|
||||||
&self.info
|
|
||||||
}
|
|
||||||
|
|
||||||
fn depth(&self) -> usize {
|
|
||||||
self.depth
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inc_sstore_clears(&mut self) {
|
|
||||||
self.sstore_clears += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_stack_underflow() {
|
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
|
||||||
let code = "01600055".from_hex().unwrap();
|
|
||||||
|
|
||||||
let mut params = ActionParams::default();
|
|
||||||
params.address = address.clone();
|
|
||||||
params.gas = U256::from(100_000);
|
|
||||||
params.code = Some(Arc::new(code));
|
|
||||||
let mut ext = FakeExt::new();
|
|
||||||
|
|
||||||
let err = {
|
|
||||||
let mut vm : Box<evm::Evm> = Box::new(super::interpreter::Interpreter::<usize>::new(Arc::new(super::interpreter::SharedCache::default())));
|
|
||||||
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
|
|
||||||
};
|
|
||||||
|
|
||||||
match err {
|
|
||||||
evm::Error::StackUnderflow {wanted, on_stack, ..} => {
|
|
||||||
assert_eq!(wanted, 2);
|
|
||||||
assert_eq!(on_stack, 0);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
assert!(false, "Expected StackUndeflow")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
evm_test!{test_add: test_add_jit, test_add_int}
|
evm_test!{test_add: test_add_jit, test_add_int}
|
||||||
fn test_add(factory: super::Factory) {
|
fn test_add(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
@ -849,7 +650,7 @@ fn test_badinstruction_int() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match err {
|
match err {
|
||||||
evm::Error::BadInstruction { instruction: 0xaf } => (),
|
vm::Error::BadInstruction { instruction: 0xaf } => (),
|
||||||
_ => assert!(false, "Expected bad instruction")
|
_ => assert!(false, "Expected bad instruction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ ethcore-io = { path = "../../util/io" }
|
|||||||
ethcore-ipc = { path = "../../ipc/rpc", optional = true }
|
ethcore-ipc = { path = "../../ipc/rpc", optional = true }
|
||||||
ethcore-devtools = { path = "../../devtools" }
|
ethcore-devtools = { path = "../../devtools" }
|
||||||
evm = { path = "../evm" }
|
evm = { path = "../evm" }
|
||||||
|
vm = { path = "../vm" }
|
||||||
rlp = { path = "../../util/rlp" }
|
rlp = { path = "../../util/rlp" }
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
smallvec = "0.4"
|
smallvec = "0.4"
|
||||||
|
@ -405,6 +405,7 @@ impl HeaderChain {
|
|||||||
|
|
||||||
match id {
|
match id {
|
||||||
BlockId::Earliest | BlockId::Number(0) => Some(self.genesis_header.clone()),
|
BlockId::Earliest | BlockId::Number(0) => Some(self.genesis_header.clone()),
|
||||||
|
BlockId::Hash(hash) if hash == self.genesis_hash() => { Some(self.genesis_header.clone()) }
|
||||||
BlockId::Hash(hash) => load_from_db(hash),
|
BlockId::Hash(hash) => load_from_db(hash),
|
||||||
BlockId::Number(num) => {
|
BlockId::Number(num) => {
|
||||||
if self.best_block.read().number < num { return None }
|
if self.best_block.read().number < num { return None }
|
||||||
@ -781,4 +782,18 @@ mod tests {
|
|||||||
assert_eq!(chain.block_header(BlockId::Latest).unwrap().number(), 10);
|
assert_eq!(chain.block_header(BlockId::Latest).unwrap().number(), 10);
|
||||||
assert!(chain.candidates.read().get(&100).is_some())
|
assert!(chain.candidates.read().get(&100).is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn genesis_header_available() {
|
||||||
|
let spec = Spec::new_test();
|
||||||
|
let genesis_header = spec.genesis_header();
|
||||||
|
let db = make_db();
|
||||||
|
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
|
||||||
|
|
||||||
|
let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap();
|
||||||
|
|
||||||
|
assert!(chain.block_header(BlockId::Earliest).is_some());
|
||||||
|
assert!(chain.block_header(BlockId::Number(0)).is_some());
|
||||||
|
assert!(chain.block_header(BlockId::Hash(genesis_header.hash())).is_some());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@ pub struct Config {
|
|||||||
pub db_wal: bool,
|
pub db_wal: bool,
|
||||||
/// Should it do full verification of blocks?
|
/// Should it do full verification of blocks?
|
||||||
pub verify_full: bool,
|
pub verify_full: bool,
|
||||||
|
/// Should it check the seal of blocks?
|
||||||
|
pub check_seal: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -69,6 +71,7 @@ impl Default for Config {
|
|||||||
db_compaction: CompactionProfile::default(),
|
db_compaction: CompactionProfile::default(),
|
||||||
db_wal: true,
|
db_wal: true,
|
||||||
verify_full: true,
|
verify_full: true,
|
||||||
|
check_seal: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +171,7 @@ impl Client {
|
|||||||
let gh = ::rlp::encode(&spec.genesis_header());
|
let gh = ::rlp::encode(&spec.genesis_header());
|
||||||
|
|
||||||
Ok(Client {
|
Ok(Client {
|
||||||
queue: HeaderQueue::new(config.queue, spec.engine.clone(), io_channel, true),
|
queue: HeaderQueue::new(config.queue, spec.engine.clone(), io_channel, config.check_seal),
|
||||||
engine: spec.engine.clone(),
|
engine: spec.engine.clone(),
|
||||||
chain: HeaderChain::new(db.clone(), chain_col, &gh, cache)?,
|
chain: HeaderChain::new(db.clone(), chain_col, &gh, cache)?,
|
||||||
report: RwLock::new(ClientReport::default()),
|
report: RwLock::new(ClientReport::default()),
|
||||||
@ -282,6 +285,7 @@ impl Client {
|
|||||||
let mut good = Vec::new();
|
let mut good = Vec::new();
|
||||||
for verified_header in self.queue.drain(MAX) {
|
for verified_header in self.queue.drain(MAX) {
|
||||||
let (num, hash) = (verified_header.number(), verified_header.hash());
|
let (num, hash) = (verified_header.number(), verified_header.hash());
|
||||||
|
trace!(target: "client", "importing block {}", num);
|
||||||
|
|
||||||
if self.verify_full && !self.check_header(&mut bad, &verified_header) {
|
if self.verify_full && !self.check_header(&mut bad, &verified_header) {
|
||||||
continue
|
continue
|
||||||
@ -381,13 +385,17 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if should skip, false otherwise. may push onto bad if
|
// return false if should skip, true otherwise. may push onto bad if
|
||||||
// should skip.
|
// should skip.
|
||||||
fn check_header(&self, bad: &mut Vec<H256>, verified_header: &Header) -> bool {
|
fn check_header(&self, bad: &mut Vec<H256>, verified_header: &Header) -> bool {
|
||||||
let hash = verified_header.hash();
|
let hash = verified_header.hash();
|
||||||
let parent_header = match self.chain.block_header(BlockId::Hash(*verified_header.parent_hash())) {
|
let parent_header = match self.chain.block_header(BlockId::Hash(*verified_header.parent_hash())) {
|
||||||
Some(header) => header,
|
Some(header) => header,
|
||||||
None => return false, // skip import of block with missing parent.
|
None => {
|
||||||
|
trace!(target: "client", "No parent for block ({}, {})",
|
||||||
|
verified_header.number(), hash);
|
||||||
|
return false // skip import of block with missing parent.
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Verify Block Family
|
// Verify Block Family
|
||||||
|
@ -80,6 +80,7 @@ extern crate serde;
|
|||||||
extern crate smallvec;
|
extern crate smallvec;
|
||||||
extern crate stats;
|
extern crate stats;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
extern crate vm;
|
||||||
|
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
extern crate ethcore_ipc as ipc;
|
extern crate ethcore_ipc as ipc;
|
||||||
|
@ -806,6 +806,9 @@ impl LightProtocol {
|
|||||||
trace!(target: "pip", "Connected peer with chain head {:?}", (status.head_hash, status.head_num));
|
trace!(target: "pip", "Connected peer with chain head {:?}", (status.head_hash, status.head_num));
|
||||||
|
|
||||||
if (status.network_id, status.genesis_hash) != (self.network_id, self.genesis_hash) {
|
if (status.network_id, status.genesis_hash) != (self.network_id, self.genesis_hash) {
|
||||||
|
trace!(target: "pip", "peer {} wrong network: network_id is {} vs our {}, gh is {} vs our {}",
|
||||||
|
peer, status.network_id, self.network_id, status.genesis_hash, self.genesis_hash);
|
||||||
|
|
||||||
return Err(Error::WrongNetwork);
|
return Err(Error::WrongNetwork);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,13 +54,21 @@ struct Peer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Peer {
|
impl Peer {
|
||||||
// whether this peer can fulfill the
|
// whether this peer can fulfill the necessary capabilities for the given
|
||||||
fn can_fulfill(&self, c: &Capabilities) -> bool {
|
// request.
|
||||||
let caps = &self.capabilities;
|
fn can_fulfill(&self, request: &Capabilities) -> bool {
|
||||||
|
let local_caps = &self.capabilities;
|
||||||
|
let can_serve_since = |req, local| {
|
||||||
|
match (req, local) {
|
||||||
|
(Some(request_block), Some(serve_since)) => request_block >= serve_since,
|
||||||
|
(Some(_), None) => false,
|
||||||
|
(None, _) => true,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
caps.serve_headers == c.serve_headers &&
|
local_caps.serve_headers >= request.serve_headers &&
|
||||||
caps.serve_chain_since >= c.serve_chain_since &&
|
can_serve_since(request.serve_chain_since, local_caps.serve_chain_since) &&
|
||||||
caps.serve_state_since >= c.serve_chain_since
|
can_serve_since(request.serve_state_since, local_caps.serve_state_since)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +252,7 @@ impl OnDemand {
|
|||||||
peers: RwLock::new(HashMap::new()),
|
peers: RwLock::new(HashMap::new()),
|
||||||
in_transit: RwLock::new(HashMap::new()),
|
in_transit: RwLock::new(HashMap::new()),
|
||||||
cache: cache,
|
cache: cache,
|
||||||
no_immediate_dispatch: true,
|
no_immediate_dispatch: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +274,6 @@ impl OnDemand {
|
|||||||
-> Result<Receiver<Vec<Response>>, basic_request::NoSuchOutput>
|
-> Result<Receiver<Vec<Response>>, basic_request::NoSuchOutput>
|
||||||
{
|
{
|
||||||
let (sender, receiver) = oneshot::channel();
|
let (sender, receiver) = oneshot::channel();
|
||||||
|
|
||||||
if requests.is_empty() {
|
if requests.is_empty() {
|
||||||
assert!(sender.send(Vec::new()).is_ok(), "receiver still in scope; qed");
|
assert!(sender.send(Vec::new()).is_ok(), "receiver still in scope; qed");
|
||||||
return Ok(receiver);
|
return Ok(receiver);
|
||||||
@ -335,6 +342,7 @@ impl OnDemand {
|
|||||||
// dispatch pending requests, and discard those for which the corresponding
|
// dispatch pending requests, and discard those for which the corresponding
|
||||||
// receiver has been dropped.
|
// receiver has been dropped.
|
||||||
fn dispatch_pending(&self, ctx: &BasicContext) {
|
fn dispatch_pending(&self, ctx: &BasicContext) {
|
||||||
|
|
||||||
// wrapper future for calling `poll_cancel` on our `Senders` to preserve
|
// wrapper future for calling `poll_cancel` on our `Senders` to preserve
|
||||||
// the invariant that it's always within a task.
|
// the invariant that it's always within a task.
|
||||||
struct CheckHangup<'a, T: 'a>(&'a mut Sender<T>);
|
struct CheckHangup<'a, T: 'a>(&'a mut Sender<T>);
|
||||||
@ -360,6 +368,8 @@ impl OnDemand {
|
|||||||
if self.pending.read().is_empty() { return }
|
if self.pending.read().is_empty() { return }
|
||||||
let mut pending = self.pending.write();
|
let mut pending = self.pending.write();
|
||||||
|
|
||||||
|
debug!(target: "on_demand", "Attempting to dispatch {} pending requests", pending.len());
|
||||||
|
|
||||||
// iterate over all pending requests, and check them for hang-up.
|
// iterate over all pending requests, and check them for hang-up.
|
||||||
// then, try and find a peer who can serve it.
|
// then, try and find a peer who can serve it.
|
||||||
let peers = self.peers.read();
|
let peers = self.peers.read();
|
||||||
@ -378,16 +388,21 @@ impl OnDemand {
|
|||||||
|
|
||||||
match ctx.request_from(*peer_id, pending.net_requests.clone()) {
|
match ctx.request_from(*peer_id, pending.net_requests.clone()) {
|
||||||
Ok(req_id) => {
|
Ok(req_id) => {
|
||||||
|
trace!(target: "on_demand", "Dispatched request {} to peer {}", req_id, peer_id);
|
||||||
self.in_transit.write().insert(req_id, pending);
|
self.in_transit.write().insert(req_id, pending);
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
Err(net::Error::NoCredits) => {}
|
Err(net::Error::NoCredits) | Err(net::Error::NotServer) => {}
|
||||||
Err(e) => debug!(target: "on_demand", "Error dispatching request to peer: {}", e),
|
Err(e) => debug!(target: "on_demand", "Error dispatching request to peer: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: maximum number of failures _when we have peers_.
|
||||||
Some(pending)
|
Some(pending)
|
||||||
})
|
})
|
||||||
.collect(); // `pending` now contains all requests we couldn't dispatch.
|
.collect(); // `pending` now contains all requests we couldn't dispatch.
|
||||||
|
|
||||||
|
debug!(target: "on_demand", "Was unable to dispatch {} requests.", pending.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
// submit a pending request set. attempts to answer from cache before
|
// submit a pending request set. attempts to answer from cache before
|
||||||
@ -395,6 +410,7 @@ impl OnDemand {
|
|||||||
fn submit_pending(&self, ctx: &BasicContext, mut pending: Pending) {
|
fn submit_pending(&self, ctx: &BasicContext, mut pending: Pending) {
|
||||||
// answer as many requests from cache as we can, and schedule for dispatch
|
// answer as many requests from cache as we can, and schedule for dispatch
|
||||||
// if incomplete.
|
// if incomplete.
|
||||||
|
|
||||||
pending.answer_from_cache(&*self.cache);
|
pending.answer_from_cache(&*self.cache);
|
||||||
if let Some(mut pending) = pending.try_complete() {
|
if let Some(mut pending) = pending.try_complete() {
|
||||||
pending.update_net_requests();
|
pending.update_net_requests();
|
||||||
|
@ -24,7 +24,7 @@ use ethcore::engines::Engine;
|
|||||||
use ethcore::receipt::Receipt;
|
use ethcore::receipt::Receipt;
|
||||||
use ethcore::state::{self, ProvedExecution};
|
use ethcore::state::{self, ProvedExecution};
|
||||||
use ethcore::transaction::SignedTransaction;
|
use ethcore::transaction::SignedTransaction;
|
||||||
use evm::env_info::EnvInfo;
|
use vm::EnvInfo;
|
||||||
|
|
||||||
use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field};
|
use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field};
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"authorityRound": {
|
"authorityRound": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"stepDuration": 1,
|
"stepDuration": 1,
|
||||||
"startStep": 2,
|
"startStep": 2,
|
||||||
"validators": {
|
"validators": {
|
||||||
@ -17,6 +16,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"basicAuthority": {
|
"basicAuthority": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"validators": {
|
"validators": {
|
||||||
"list": ["0x9cce34f7ab185c7aba1b7c8140d620b4bda941d6"]
|
"list": ["0x9cce34f7ab185c7aba1b7c8140d620b4bda941d6"]
|
||||||
@ -12,6 +11,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0100000",
|
"accountStartNonce": "0x0100000",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -4,12 +4,14 @@
|
|||||||
"null": null
|
"null": null
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x2"
|
"networkID" : "0x2"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"seal": {
|
"seal": {
|
||||||
"generic": "0x"
|
"generic": "0x"
|
||||||
},
|
},
|
||||||
|
@ -4,15 +4,11 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
|
||||||
"homesteadTransition": 1150000,
|
"homesteadTransition": 1150000,
|
||||||
"eip150Transition": 2500000,
|
"eip150Transition": 2500000,
|
||||||
"eip155Transition": 3000000,
|
|
||||||
"eip160Transition": 3000000,
|
"eip160Transition": 3000000,
|
||||||
"ecip1010PauseTransition": 3000000,
|
"ecip1010PauseTransition": 3000000,
|
||||||
"ecip1010ContinueTransition": 5000000,
|
"ecip1010ContinueTransition": 5000000,
|
||||||
@ -24,6 +20,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
@ -31,6 +30,8 @@
|
|||||||
"chainID": "0x3d",
|
"chainID": "0x3d",
|
||||||
"forkBlock": "0x1d4c00",
|
"forkBlock": "0x1d4c00",
|
||||||
"forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f",
|
"forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f",
|
||||||
|
"eip155Transition": 3000000,
|
||||||
|
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff"
|
||||||
},
|
},
|
||||||
|
@ -3,15 +3,11 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
|
||||||
"homesteadTransition": "0x0",
|
"homesteadTransition": "0x0",
|
||||||
"eip150Transition": "0x0",
|
"eip150Transition": "0x0",
|
||||||
"eip155Transition": "0x7fffffffffffffff",
|
|
||||||
"eip160Transition": "0x7fffffffffffffff",
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff",
|
"eip161dTransition": "0x7fffffffffffffff",
|
||||||
@ -20,12 +16,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x1",
|
"networkID" : "0x1",
|
||||||
"eip98Transition": "0x7fffffffffffffff",
|
"eip98Transition": "0x7fffffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffffff"
|
"eip86Transition": "0x7fffffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -3,15 +3,11 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
|
||||||
"homesteadTransition": "0x0",
|
"homesteadTransition": "0x0",
|
||||||
"eip150Transition": "0x0",
|
"eip150Transition": "0x0",
|
||||||
"eip155Transition": "0x7fffffffffffffff",
|
|
||||||
"eip160Transition": "0x0",
|
"eip160Transition": "0x0",
|
||||||
"eip161abcTransition": "0x0",
|
"eip161abcTransition": "0x0",
|
||||||
"eip161dTransition": "0x0",
|
"eip161dTransition": "0x0",
|
||||||
@ -20,12 +16,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x1",
|
"networkID" : "0x1",
|
||||||
"eip98Transition": "0x7fffffffffffffff",
|
"eip98Transition": "0x7fffffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffffff"
|
"eip86Transition": "0x7fffffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -4,19 +4,15 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"difficultyIncrementDivisor": "60",
|
"difficultyIncrementDivisor": "60",
|
||||||
"durationLimit": "0x3C",
|
"durationLimit": "0x3C",
|
||||||
"blockReward": "0x6f05b59d3b200000",
|
|
||||||
"registrar" : "0x6c221ca53705f3497ec90ca7b84c59ae7382fc21",
|
|
||||||
"homesteadTransition": "0x30d40",
|
"homesteadTransition": "0x30d40",
|
||||||
"difficultyHardforkTransition": "0x59d9",
|
"difficultyHardforkTransition": "0x59d9",
|
||||||
"difficultyHardforkBoundDivisor": "0x0200",
|
"difficultyHardforkBoundDivisor": "0x0200",
|
||||||
"bombDefuseTransition": "0x30d40",
|
"bombDefuseTransition": "0x30d40",
|
||||||
"eip150Transition": "0x927C0",
|
"eip150Transition": "0x927C0",
|
||||||
"eip155Transition": "0x927C0",
|
|
||||||
"eip160Transition": "0x927C0",
|
"eip160Transition": "0x927C0",
|
||||||
"eip161abcTransition": "0x927C0",
|
"eip161abcTransition": "0x927C0",
|
||||||
"eip161dTransition": "0x927C0"
|
"eip161dTransition": "0x927C0"
|
||||||
@ -24,6 +20,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x6f05b59d3b200000",
|
||||||
|
"registrar" : "0x6c221ca53705f3497ec90ca7b84c59ae7382fc21",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
@ -31,7 +30,8 @@
|
|||||||
"chainID": "0x2",
|
"chainID": "0x2",
|
||||||
"subprotocolName": "exp",
|
"subprotocolName": "exp",
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff",
|
||||||
|
"eip155Transition": "0x927C0"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -4,12 +4,9 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xe3389675d0338462dC76C6f9A3e432550c36A142",
|
|
||||||
"homesteadTransition": "0x118c30",
|
"homesteadTransition": "0x118c30",
|
||||||
"daoHardforkTransition": "0x1d4c00",
|
"daoHardforkTransition": "0x1d4c00",
|
||||||
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
|
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
|
||||||
@ -132,7 +129,6 @@
|
|||||||
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
||||||
],
|
],
|
||||||
"eip150Transition": "0x259518",
|
"eip150Transition": "0x259518",
|
||||||
"eip155Transition": 2675000,
|
|
||||||
"eip160Transition": 2675000,
|
"eip160Transition": 2675000,
|
||||||
"eip161abcTransition": 2675000,
|
"eip161abcTransition": 2675000,
|
||||||
"eip161dTransition": 2675000,
|
"eip161dTransition": 2675000,
|
||||||
@ -141,12 +137,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xe3389675d0338462dC76C6f9A3e432550c36A142",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x1",
|
"networkID" : "0x1",
|
||||||
"forkBlock": "0x1d4c00",
|
"forkBlock": "0x1d4c00",
|
||||||
"forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb",
|
"forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb",
|
||||||
|
"eip155Transition": 2675000,
|
||||||
|
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff"
|
||||||
},
|
},
|
||||||
|
@ -3,12 +3,9 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
|
||||||
"homesteadTransition": "0x118c30",
|
"homesteadTransition": "0x118c30",
|
||||||
"daoHardforkTransition": "0x1d4c00",
|
"daoHardforkTransition": "0x1d4c00",
|
||||||
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
|
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
|
||||||
@ -131,7 +128,6 @@
|
|||||||
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
||||||
],
|
],
|
||||||
"eip150Transition": "0x7fffffffffffffff",
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
"eip155Transition": "0x7fffffffffffffff",
|
|
||||||
"eip160Transition": "0x7fffffffffffffff",
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff"
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
@ -139,12 +135,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x1",
|
"networkID" : "0x1",
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -3,15 +3,11 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
|
||||||
"homesteadTransition": "0x7fffffffffffffff",
|
"homesteadTransition": "0x7fffffffffffffff",
|
||||||
"eip150Transition": "0x7fffffffffffffff",
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
"eip155Transition": "0x7fffffffffffffff",
|
|
||||||
"eip160Transition": "0x7fffffffffffffff",
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff"
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
@ -19,12 +15,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x1",
|
"networkID" : "0x1",
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -3,15 +3,11 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
|
||||||
"homesteadTransition": "0x0",
|
"homesteadTransition": "0x0",
|
||||||
"eip150Transition": "0x7fffffffffffffff",
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
"eip155Transition": "0x7fffffffffffffff",
|
|
||||||
"eip160Transition": "0x7fffffffffffffff",
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff"
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
@ -19,12 +15,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x1",
|
"networkID" : "0x1",
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -4,10 +4,7 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"authorityRound": {
|
"authorityRound": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x400",
|
|
||||||
"registrar" : "0xfAb104398BBefbd47752E7702D9fE23047E1Bca3",
|
|
||||||
"stepDuration": "4",
|
"stepDuration": "4",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"validators" : {
|
"validators" : {
|
||||||
"list": [
|
"list": [
|
||||||
"0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED",
|
"0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED",
|
||||||
@ -25,16 +22,19 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"validateScoreTransition": 1000000,
|
"validateScoreTransition": 1000000,
|
||||||
"eip155Transition": 1000000,
|
|
||||||
"validateStepTransition": 1500000
|
"validateStepTransition": 1500000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x400",
|
||||||
|
"registrar" : "0xfAb104398BBefbd47752E7702D9fE23047E1Bca3",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x2A",
|
"networkID" : "0x2A",
|
||||||
"validateReceiptsTransition" : 1000000
|
"validateReceiptsTransition" : 1000000,
|
||||||
|
"eip155Transition": 1000000
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -3,15 +3,12 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
|
||||||
"homesteadTransition": "0x0",
|
"homesteadTransition": "0x0",
|
||||||
"eip150Transition": "0x0",
|
"eip150Transition": "0x0",
|
||||||
"eip155Transition": "0x0",
|
|
||||||
"eip160Transition": "0x0",
|
"eip160Transition": "0x0",
|
||||||
"eip161abcTransition": "0x0",
|
"eip161abcTransition": "0x0",
|
||||||
"eip161dTransition": "0x0",
|
"eip161dTransition": "0x0",
|
||||||
@ -20,6 +17,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
@ -27,7 +27,8 @@
|
|||||||
"eip98Transition": "0x0",
|
"eip98Transition": "0x0",
|
||||||
"eip86Transition": "0x0",
|
"eip86Transition": "0x0",
|
||||||
"eip140Transition": "0x0",
|
"eip140Transition": "0x0",
|
||||||
"eip210Transition": "0x0"
|
"eip210Transition": "0x0",
|
||||||
|
"eip155Transition": "0x0"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -4,15 +4,11 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d",
|
|
||||||
"homesteadTransition": 494000,
|
"homesteadTransition": 494000,
|
||||||
"eip150Transition": 1783000,
|
"eip150Transition": 1783000,
|
||||||
"eip155Transition": 1915000,
|
|
||||||
"eip160Transition": 1915000,
|
"eip160Transition": 1915000,
|
||||||
"ecip1010PauseTransition": 1915000,
|
"ecip1010PauseTransition": 1915000,
|
||||||
"ecip1010ContinueTransition": 3415000,
|
"ecip1010ContinueTransition": 3415000,
|
||||||
@ -23,6 +19,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d",
|
||||||
"accountStartNonce": "0x0100000",
|
"accountStartNonce": "0x0100000",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
@ -30,6 +29,8 @@
|
|||||||
"chainID": "0x3e",
|
"chainID": "0x3e",
|
||||||
"forkBlock": "0x1b34d8",
|
"forkBlock": "0x1b34d8",
|
||||||
"forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145",
|
"forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145",
|
||||||
|
"eip155Transition": 1915000,
|
||||||
|
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff"
|
||||||
},
|
},
|
||||||
|
@ -3,15 +3,11 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x08",
|
"durationLimit": "0x08",
|
||||||
"blockReward": "0x14D1120D7B160000",
|
|
||||||
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
|
|
||||||
"homesteadTransition": "0x7fffffffffffffff",
|
"homesteadTransition": "0x7fffffffffffffff",
|
||||||
"eip150Transition": "0x7fffffffffffffff",
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
"eip155Transition": "0x7fffffffffffffff",
|
|
||||||
"eip160Transition": "0x7fffffffffffffff",
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff"
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
@ -19,12 +15,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x14D1120D7B160000",
|
||||||
|
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x0400",
|
"maximumExtraDataSize": "0x0400",
|
||||||
"minGasLimit": "125000",
|
"minGasLimit": "125000",
|
||||||
"networkID" : "0x0",
|
"networkID" : "0x0",
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -4,15 +4,11 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar": "0x81a4b044831c4f12ba601adb9274516939e9b8a2",
|
|
||||||
"homesteadTransition": 0,
|
"homesteadTransition": 0,
|
||||||
"eip150Transition": 0,
|
"eip150Transition": 0,
|
||||||
"eip155Transition": 10,
|
|
||||||
"eip160Transition": 10,
|
"eip160Transition": 10,
|
||||||
"eip161abcTransition": 10,
|
"eip161abcTransition": 10,
|
||||||
"eip161dTransition": 10,
|
"eip161dTransition": 10,
|
||||||
@ -21,12 +17,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar": "0x81a4b044831c4f12ba601adb9274516939e9b8a2",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x3",
|
"networkID" : "0x3",
|
||||||
"forkBlock": 641350,
|
"forkBlock": 641350,
|
||||||
"forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb",
|
"forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb",
|
||||||
|
"eip155Transition": 10,
|
||||||
|
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff"
|
||||||
},
|
},
|
||||||
|
@ -3,12 +3,9 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"Ethash": {
|
"Ethash": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"minimumDifficulty": "0x020000",
|
"minimumDifficulty": "0x020000",
|
||||||
"difficultyBoundDivisor": "0x0800",
|
"difficultyBoundDivisor": "0x0800",
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"blockReward": "0x4563918244F40000",
|
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
|
||||||
"homesteadTransition": "0x5",
|
"homesteadTransition": "0x5",
|
||||||
"daoHardforkTransition": "0x8",
|
"daoHardforkTransition": "0x8",
|
||||||
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
|
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
|
||||||
@ -131,7 +128,6 @@
|
|||||||
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
||||||
],
|
],
|
||||||
"eip150Transition": "0xa",
|
"eip150Transition": "0xa",
|
||||||
"eip155Transition": "0x7fffffffffffffff",
|
|
||||||
"eip160Transition": "0x7fffffffffffffff",
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff"
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
@ -139,12 +135,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"accountStartNonce": "0x00",
|
"accountStartNonce": "0x00",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x1",
|
"networkID" : "0x1",
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "DevelopmentChain",
|
"name": "DevelopmentChain",
|
||||||
"engine": {
|
"engine": {
|
||||||
"instantSeal": {
|
"instantSeal": null
|
||||||
"params": {
|
|
||||||
"registrar": "0x0000000000000000000000000000000000000005"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"null": null
|
"null": null
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"null": null
|
"null": null
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"tendermint": {
|
"tendermint": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"validators" : {
|
"validators" : {
|
||||||
"list": [
|
"list": [
|
||||||
"0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1",
|
"0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1",
|
||||||
@ -18,6 +17,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"authorityRound": {
|
"authorityRound": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"stepDuration": 1,
|
"stepDuration": 1,
|
||||||
"startStep": 2,
|
"startStep": 2,
|
||||||
"validators": {
|
"validators": {
|
||||||
@ -14,6 +13,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"basicAuthority": {
|
"basicAuthority": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"durationLimit": "0x0d",
|
"durationLimit": "0x0d",
|
||||||
"validators": {
|
"validators": {
|
||||||
"multi": {
|
"multi": {
|
||||||
@ -15,6 +14,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 8361f18c7ea133d9b85edf7dea02f05b9feb1938
|
Subproject commit 04c9d84c5fe5c3ad707be58664c7e72b97cc9996
|
@ -25,7 +25,7 @@ use util::{Bytes, Address, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RL
|
|||||||
use util::error::{Mismatch, OutOfBounds};
|
use util::error::{Mismatch, OutOfBounds};
|
||||||
|
|
||||||
use basic_types::{LogBloom, Seal};
|
use basic_types::{LogBloom, Seal};
|
||||||
use evm::env_info::{EnvInfo, LastHashes};
|
use vm::{EnvInfo, LastHashes};
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
use error::{Error, BlockError, TransactionError};
|
use error::{Error, BlockError, TransactionError};
|
||||||
use factory::Factories;
|
use factory::Factories;
|
||||||
@ -667,7 +667,7 @@ mod tests {
|
|||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
use evm::env_info::LastHashes;
|
use vm::LastHashes;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use header::Header;
|
use header::Header;
|
||||||
use factory::Factories;
|
use factory::Factories;
|
||||||
|
@ -36,9 +36,9 @@ impl From<&'static str> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<::evm::Error> for Error {
|
impl Into<::vm::Error> for Error {
|
||||||
fn into(self) -> ::evm::Error {
|
fn into(self) -> ::vm::Error {
|
||||||
::evm::Error::BuiltIn(self.0)
|
::vm::Error::BuiltIn(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,9 +42,8 @@ use client::{
|
|||||||
};
|
};
|
||||||
use encoded;
|
use encoded;
|
||||||
use engines::{Engine, EpochTransition};
|
use engines::{Engine, EpochTransition};
|
||||||
use evm::env_info::EnvInfo;
|
|
||||||
use evm::env_info::LastHashes;
|
|
||||||
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
|
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
|
||||||
|
use vm::{EnvInfo, LastHashes};
|
||||||
use evm::{Factory as EvmFactory, Schedule};
|
use evm::{Factory as EvmFactory, Schedule};
|
||||||
use executive::{Executive, Executed, TransactOptions, contract_address};
|
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||||
use factory::Factories;
|
use factory::Factories;
|
||||||
|
@ -23,7 +23,7 @@ use util::kvdb::{self, KeyValueDB};
|
|||||||
use {state, state_db, client, executive, trace, db, spec};
|
use {state, state_db, client, executive, trace, db, spec};
|
||||||
use factory::Factories;
|
use factory::Factories;
|
||||||
use evm::{self, VMType};
|
use evm::{self, VMType};
|
||||||
use evm::action_params::ActionParams;
|
use vm::{self, ActionParams};
|
||||||
|
|
||||||
/// EVM test Error.
|
/// EVM test Error.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -31,7 +31,7 @@ pub enum EvmTestError {
|
|||||||
/// Trie integrity error.
|
/// Trie integrity error.
|
||||||
Trie(util::TrieError),
|
Trie(util::TrieError),
|
||||||
/// EVM error.
|
/// EVM error.
|
||||||
Evm(evm::Error),
|
Evm(vm::Error),
|
||||||
/// Initialization error.
|
/// Initialization error.
|
||||||
Initialization(::error::Error),
|
Initialization(::error::Error),
|
||||||
/// Low-level database error.
|
/// Low-level database error.
|
||||||
|
@ -40,7 +40,7 @@ pub use types::pruning_info::PruningInfo;
|
|||||||
pub use types::call_analytics::CallAnalytics;
|
pub use types::call_analytics::CallAnalytics;
|
||||||
|
|
||||||
pub use executive::{Executed, Executive, TransactOptions};
|
pub use executive::{Executed, Executive, TransactOptions};
|
||||||
pub use evm::env_info::{LastHashes, EnvInfo};
|
pub use vm::{LastHashes, EnvInfo};
|
||||||
|
|
||||||
pub use error::{BlockImportError, TransactionImportError, TransactionImportResult};
|
pub use error::{BlockImportError, TransactionImportError, TransactionImportResult};
|
||||||
pub use verification::VerifierType;
|
pub use verification::VerifierType;
|
||||||
|
@ -36,7 +36,8 @@ use log_entry::LocalizedLogEntry;
|
|||||||
use receipt::{Receipt, LocalizedReceipt};
|
use receipt::{Receipt, LocalizedReceipt};
|
||||||
use blockchain::extras::BlockReceipts;
|
use blockchain::extras::BlockReceipts;
|
||||||
use error::{ImportResult, Error as EthcoreError};
|
use error::{ImportResult, Error as EthcoreError};
|
||||||
use evm::{Factory as EvmFactory, VMType, Schedule};
|
use evm::{Factory as EvmFactory, VMType};
|
||||||
|
use vm::Schedule;
|
||||||
use miner::{Miner, MinerService, TransactionImportResult};
|
use miner::{Miner, MinerService, TransactionImportResult};
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use types::basic_account::BasicAccount;
|
use types::basic_account::BasicAccount;
|
||||||
|
@ -19,7 +19,7 @@ use std::collections::BTreeMap;
|
|||||||
use block::{OpenBlock, SealedBlock, ClosedBlock};
|
use block::{OpenBlock, SealedBlock, ClosedBlock};
|
||||||
use blockchain::TreeRoute;
|
use blockchain::TreeRoute;
|
||||||
use encoded;
|
use encoded;
|
||||||
use evm::env_info::LastHashes;
|
use vm::LastHashes;
|
||||||
use error::{ImportResult, CallError, Error as EthcoreError};
|
use error::{ImportResult, CallError, Error as EthcoreError};
|
||||||
use error::{TransactionImportResult, BlockImportError};
|
use error::{TransactionImportResult, BlockImportError};
|
||||||
use evm::{Factory as EvmFactory, Schedule};
|
use evm::{Factory as EvmFactory, Schedule};
|
||||||
|
@ -47,22 +47,14 @@ mod finality;
|
|||||||
|
|
||||||
/// `AuthorityRound` params.
|
/// `AuthorityRound` params.
|
||||||
pub struct AuthorityRoundParams {
|
pub struct AuthorityRoundParams {
|
||||||
/// Gas limit divisor.
|
|
||||||
pub gas_limit_bound_divisor: U256,
|
|
||||||
/// Time to wait before next block or authority switching.
|
/// Time to wait before next block or authority switching.
|
||||||
pub step_duration: Duration,
|
pub step_duration: Duration,
|
||||||
/// Block reward.
|
|
||||||
pub block_reward: U256,
|
|
||||||
/// Namereg contract address.
|
|
||||||
pub registrar: Address,
|
|
||||||
/// Starting step,
|
/// Starting step,
|
||||||
pub start_step: Option<u64>,
|
pub start_step: Option<u64>,
|
||||||
/// Valid validators.
|
/// Valid validators.
|
||||||
pub validators: Box<ValidatorSet>,
|
pub validators: Box<ValidatorSet>,
|
||||||
/// Chain score validation transition block.
|
/// Chain score validation transition block.
|
||||||
pub validate_score_transition: u64,
|
pub validate_score_transition: u64,
|
||||||
/// Number of first block where EIP-155 rules are validated.
|
|
||||||
pub eip155_transition: u64,
|
|
||||||
/// Monotonic step validation transition block.
|
/// Monotonic step validation transition block.
|
||||||
pub validate_step_transition: u64,
|
pub validate_step_transition: u64,
|
||||||
/// Immediate transitions.
|
/// Immediate transitions.
|
||||||
@ -72,14 +64,10 @@ pub struct AuthorityRoundParams {
|
|||||||
impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
||||||
fn from(p: ethjson::spec::AuthorityRoundParams) -> Self {
|
fn from(p: ethjson::spec::AuthorityRoundParams) -> Self {
|
||||||
AuthorityRoundParams {
|
AuthorityRoundParams {
|
||||||
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
|
|
||||||
step_duration: Duration::from_secs(p.step_duration.into()),
|
step_duration: Duration::from_secs(p.step_duration.into()),
|
||||||
validators: new_validator_set(p.validators),
|
validators: new_validator_set(p.validators),
|
||||||
block_reward: p.block_reward.map_or_else(U256::zero, Into::into),
|
|
||||||
registrar: p.registrar.map_or_else(Address::new, Into::into),
|
|
||||||
start_step: p.start_step.map(Into::into),
|
start_step: p.start_step.map(Into::into),
|
||||||
validate_score_transition: p.validate_score_transition.map_or(0, Into::into),
|
validate_score_transition: p.validate_score_transition.map_or(0, Into::into),
|
||||||
eip155_transition: p.eip155_transition.map_or(0, Into::into),
|
|
||||||
validate_step_transition: p.validate_step_transition.map_or(0, Into::into),
|
validate_step_transition: p.validate_step_transition.map_or(0, Into::into),
|
||||||
immediate_transitions: p.immediate_transitions.unwrap_or(false),
|
immediate_transitions: p.immediate_transitions.unwrap_or(false),
|
||||||
}
|
}
|
||||||
@ -214,9 +202,6 @@ impl EpochManager {
|
|||||||
/// Engine using `AuthorityRound` proof-of-authority BFT consensus.
|
/// Engine using `AuthorityRound` proof-of-authority BFT consensus.
|
||||||
pub struct AuthorityRound {
|
pub struct AuthorityRound {
|
||||||
params: CommonParams,
|
params: CommonParams,
|
||||||
gas_limit_bound_divisor: U256,
|
|
||||||
block_reward: U256,
|
|
||||||
registrar: Address,
|
|
||||||
builtins: BTreeMap<Address, Builtin>,
|
builtins: BTreeMap<Address, Builtin>,
|
||||||
transition_service: IoService<()>,
|
transition_service: IoService<()>,
|
||||||
step: Arc<Step>,
|
step: Arc<Step>,
|
||||||
@ -225,7 +210,6 @@ pub struct AuthorityRound {
|
|||||||
signer: RwLock<EngineSigner>,
|
signer: RwLock<EngineSigner>,
|
||||||
validators: Box<ValidatorSet>,
|
validators: Box<ValidatorSet>,
|
||||||
validate_score_transition: u64,
|
validate_score_transition: u64,
|
||||||
eip155_transition: u64,
|
|
||||||
validate_step_transition: u64,
|
validate_step_transition: u64,
|
||||||
epoch_manager: Mutex<EpochManager>,
|
epoch_manager: Mutex<EpochManager>,
|
||||||
immediate_transitions: bool,
|
immediate_transitions: bool,
|
||||||
@ -362,9 +346,6 @@ impl AuthorityRound {
|
|||||||
let engine = Arc::new(
|
let engine = Arc::new(
|
||||||
AuthorityRound {
|
AuthorityRound {
|
||||||
params: params,
|
params: params,
|
||||||
gas_limit_bound_divisor: our_params.gas_limit_bound_divisor,
|
|
||||||
block_reward: our_params.block_reward,
|
|
||||||
registrar: our_params.registrar,
|
|
||||||
builtins: builtins,
|
builtins: builtins,
|
||||||
transition_service: IoService::<()>::start()?,
|
transition_service: IoService::<()>::start()?,
|
||||||
step: Arc::new(Step {
|
step: Arc::new(Step {
|
||||||
@ -377,7 +358,6 @@ impl AuthorityRound {
|
|||||||
signer: Default::default(),
|
signer: Default::default(),
|
||||||
validators: our_params.validators,
|
validators: our_params.validators,
|
||||||
validate_score_transition: our_params.validate_score_transition,
|
validate_score_transition: our_params.validate_score_transition,
|
||||||
eip155_transition: our_params.eip155_transition,
|
|
||||||
validate_step_transition: our_params.validate_step_transition,
|
validate_step_transition: our_params.validate_step_transition,
|
||||||
epoch_manager: Mutex::new(EpochManager::blank()),
|
epoch_manager: Mutex::new(EpochManager::blank()),
|
||||||
immediate_transitions: our_params.immediate_transitions,
|
immediate_transitions: our_params.immediate_transitions,
|
||||||
@ -433,7 +413,9 @@ impl Engine for AuthorityRound {
|
|||||||
|
|
||||||
fn params(&self) -> &CommonParams { &self.params }
|
fn params(&self) -> &CommonParams { &self.params }
|
||||||
|
|
||||||
fn additional_params(&self) -> HashMap<String, String> { hash_map!["registrar".to_owned() => self.registrar.hex()] }
|
fn additional_params(&self) -> HashMap<String, String> {
|
||||||
|
hash_map!["registrar".to_owned() => self.params().registrar.hex()]
|
||||||
|
}
|
||||||
|
|
||||||
fn builtins(&self) -> &BTreeMap<Address, Builtin> { &self.builtins }
|
fn builtins(&self) -> &BTreeMap<Address, Builtin> { &self.builtins }
|
||||||
|
|
||||||
@ -461,7 +443,7 @@ impl Engine for AuthorityRound {
|
|||||||
header.set_difficulty(new_difficulty);
|
header.set_difficulty(new_difficulty);
|
||||||
header.set_gas_limit({
|
header.set_gas_limit({
|
||||||
let gas_limit = parent.gas_limit().clone();
|
let gas_limit = parent.gas_limit().clone();
|
||||||
let bound_divisor = self.gas_limit_bound_divisor;
|
let bound_divisor = self.params().gas_limit_bound_divisor;
|
||||||
if gas_limit < gas_floor_target {
|
if gas_limit < gas_floor_target {
|
||||||
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
|
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
|
||||||
} else {
|
} else {
|
||||||
@ -476,8 +458,8 @@ impl Engine for AuthorityRound {
|
|||||||
|
|
||||||
/// Attempt to seal the block internally.
|
/// Attempt to seal the block internally.
|
||||||
///
|
///
|
||||||
/// This operation is synchronous and may (quite reasonably) not be available, in which `false` will
|
/// This operation is synchronous and may (quite reasonably) not be available, in which case
|
||||||
/// be returned.
|
/// `Seal::None` will be returned.
|
||||||
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
||||||
// first check to avoid generating signature most of the time
|
// first check to avoid generating signature most of the time
|
||||||
// (but there's still a race to the `compare_and_swap`)
|
// (but there's still a race to the `compare_and_swap`)
|
||||||
@ -532,7 +514,7 @@ impl Engine for AuthorityRound {
|
|||||||
fn on_new_block(
|
fn on_new_block(
|
||||||
&self,
|
&self,
|
||||||
block: &mut ExecutedBlock,
|
block: &mut ExecutedBlock,
|
||||||
last_hashes: Arc<::evm::env_info::LastHashes>,
|
last_hashes: Arc<::vm::LastHashes>,
|
||||||
epoch_begin: bool,
|
epoch_begin: bool,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let parent_hash = block.fields().header.parent_hash().clone();
|
let parent_hash = block.fields().header.parent_hash().clone();
|
||||||
@ -564,7 +546,8 @@ impl Engine for AuthorityRound {
|
|||||||
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
|
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
|
||||||
let fields = block.fields_mut();
|
let fields = block.fields_mut();
|
||||||
// Bestow block reward
|
// Bestow block reward
|
||||||
let res = fields.state.add_balance(fields.header.author(), &self.block_reward, CleanupMode::NoEmpty)
|
let reward = self.params().block_reward;
|
||||||
|
let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty)
|
||||||
.map_err(::error::Error::from)
|
.map_err(::error::Error::from)
|
||||||
.and_then(|_| fields.state.commit());
|
.and_then(|_| fields.state.commit());
|
||||||
// Commit state so that we can actually figure out the state root.
|
// Commit state so that we can actually figure out the state root.
|
||||||
@ -629,7 +612,7 @@ impl Engine for AuthorityRound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let gas_limit_divisor = self.gas_limit_bound_divisor;
|
let gas_limit_divisor = self.params().gas_limit_bound_divisor;
|
||||||
let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
|
let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
|
||||||
let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor;
|
let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor;
|
||||||
if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas {
|
if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas {
|
||||||
@ -819,7 +802,7 @@ impl Engine for AuthorityRound {
|
|||||||
t.check_low_s()?;
|
t.check_low_s()?;
|
||||||
|
|
||||||
if let Some(n) = t.network_id() {
|
if let Some(n) = t.network_id() {
|
||||||
if header.number() >= self.eip155_transition && n != self.params().chain_id {
|
if header.number() >= self.params().eip155_transition && n != self.params().chain_id {
|
||||||
return Err(TransactionError::InvalidNetworkId.into());
|
return Err(TransactionError::InvalidNetworkId.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1014,18 +997,19 @@ mod tests {
|
|||||||
fn reports_skipped() {
|
fn reports_skipped() {
|
||||||
let last_benign = Arc::new(AtomicUsize::new(0));
|
let last_benign = Arc::new(AtomicUsize::new(0));
|
||||||
let params = AuthorityRoundParams {
|
let params = AuthorityRoundParams {
|
||||||
gas_limit_bound_divisor: U256::from_str("400").unwrap(),
|
|
||||||
step_duration: Default::default(),
|
step_duration: Default::default(),
|
||||||
block_reward: Default::default(),
|
|
||||||
registrar: Default::default(),
|
|
||||||
start_step: Some(1),
|
start_step: Some(1),
|
||||||
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
|
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
|
||||||
validate_score_transition: 0,
|
validate_score_transition: 0,
|
||||||
validate_step_transition: 0,
|
validate_step_transition: 0,
|
||||||
eip155_transition: 0,
|
|
||||||
immediate_transitions: true,
|
immediate_transitions: true,
|
||||||
};
|
};
|
||||||
let aura = AuthorityRound::new(Default::default(), params, Default::default()).unwrap();
|
|
||||||
|
let aura = {
|
||||||
|
let mut c_params = ::spec::CommonParams::default();
|
||||||
|
c_params.gas_limit_bound_divisor = 5.into();
|
||||||
|
AuthorityRound::new(c_params, params, Default::default()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
let mut parent_header: Header = Header::default();
|
let mut parent_header: Header = Header::default();
|
||||||
parent_header.set_seal(vec![encode(&1usize).into_vec()]);
|
parent_header.set_seal(vec![encode(&1usize).into_vec()]);
|
||||||
|
@ -35,8 +35,6 @@ use super::validator_set::{ValidatorSet, SimpleList, new_validator_set};
|
|||||||
/// `BasicAuthority` params.
|
/// `BasicAuthority` params.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct BasicAuthorityParams {
|
pub struct BasicAuthorityParams {
|
||||||
/// Gas limit divisor.
|
|
||||||
pub gas_limit_bound_divisor: U256,
|
|
||||||
/// Valid signatories.
|
/// Valid signatories.
|
||||||
pub validators: ethjson::spec::ValidatorSet,
|
pub validators: ethjson::spec::ValidatorSet,
|
||||||
}
|
}
|
||||||
@ -44,7 +42,6 @@ pub struct BasicAuthorityParams {
|
|||||||
impl From<ethjson::spec::BasicAuthorityParams> for BasicAuthorityParams {
|
impl From<ethjson::spec::BasicAuthorityParams> for BasicAuthorityParams {
|
||||||
fn from(p: ethjson::spec::BasicAuthorityParams) -> Self {
|
fn from(p: ethjson::spec::BasicAuthorityParams) -> Self {
|
||||||
BasicAuthorityParams {
|
BasicAuthorityParams {
|
||||||
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
|
|
||||||
validators: p.validators,
|
validators: p.validators,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +77,6 @@ fn verify_external(header: &Header, validators: &ValidatorSet) -> Result<(), Err
|
|||||||
/// Engine using `BasicAuthority`, trivial proof-of-authority consensus.
|
/// Engine using `BasicAuthority`, trivial proof-of-authority consensus.
|
||||||
pub struct BasicAuthority {
|
pub struct BasicAuthority {
|
||||||
params: CommonParams,
|
params: CommonParams,
|
||||||
gas_limit_bound_divisor: U256,
|
|
||||||
builtins: BTreeMap<Address, Builtin>,
|
builtins: BTreeMap<Address, Builtin>,
|
||||||
signer: RwLock<EngineSigner>,
|
signer: RwLock<EngineSigner>,
|
||||||
validators: Box<ValidatorSet>,
|
validators: Box<ValidatorSet>,
|
||||||
@ -91,7 +87,6 @@ impl BasicAuthority {
|
|||||||
pub fn new(params: CommonParams, our_params: BasicAuthorityParams, builtins: BTreeMap<Address, Builtin>) -> Self {
|
pub fn new(params: CommonParams, our_params: BasicAuthorityParams, builtins: BTreeMap<Address, Builtin>) -> Self {
|
||||||
BasicAuthority {
|
BasicAuthority {
|
||||||
params: params,
|
params: params,
|
||||||
gas_limit_bound_divisor: our_params.gas_limit_bound_divisor,
|
|
||||||
builtins: builtins,
|
builtins: builtins,
|
||||||
validators: new_validator_set(our_params.validators),
|
validators: new_validator_set(our_params.validators),
|
||||||
signer: Default::default(),
|
signer: Default::default(),
|
||||||
@ -119,7 +114,7 @@ impl Engine for BasicAuthority {
|
|||||||
header.set_difficulty(parent.difficulty().clone());
|
header.set_difficulty(parent.difficulty().clone());
|
||||||
header.set_gas_limit({
|
header.set_gas_limit({
|
||||||
let gas_limit = parent.gas_limit().clone();
|
let gas_limit = parent.gas_limit().clone();
|
||||||
let bound_divisor = self.gas_limit_bound_divisor;
|
let bound_divisor = self.params().gas_limit_bound_divisor;
|
||||||
if gas_limit < gas_floor_target {
|
if gas_limit < gas_floor_target {
|
||||||
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
|
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
|
||||||
} else {
|
} else {
|
||||||
@ -172,7 +167,7 @@ impl Engine for BasicAuthority {
|
|||||||
if header.difficulty() != parent.difficulty() {
|
if header.difficulty() != parent.difficulty() {
|
||||||
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: *parent.difficulty(), found: *header.difficulty() })))
|
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: *parent.difficulty(), found: *header.difficulty() })))
|
||||||
}
|
}
|
||||||
let gas_limit_divisor = self.gas_limit_bound_divisor;
|
let gas_limit_divisor = self.params().gas_limit_bound_divisor;
|
||||||
let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
|
let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
|
||||||
let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor;
|
let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor;
|
||||||
if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas {
|
if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas {
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity 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.
|
|
||||||
|
|
||||||
// Parity 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 Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Epoch verifiers.
|
|
||||||
|
|
||||||
use error::Error;
|
|
||||||
use header::Header;
|
|
||||||
|
|
||||||
/// Verifier for all blocks within an epoch with self-contained state.
|
|
||||||
///
|
|
||||||
/// See docs on `Engine` relating to proving functions for more details.
|
|
||||||
pub trait EpochVerifier: Send + Sync {
|
|
||||||
/// Get the epoch number.
|
|
||||||
fn epoch_number(&self) -> u64;
|
|
||||||
|
|
||||||
/// Lightly verify the next block header.
|
|
||||||
/// This may not be a header belonging to a different epoch.
|
|
||||||
fn verify_light(&self, header: &Header) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Perform potentially heavier checks on the next block header.
|
|
||||||
fn verify_heavy(&self, header: &Header) -> Result<(), Error> {
|
|
||||||
self.verify_light(header)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the header is the end of an epoch.
|
|
||||||
fn is_epoch_end(&self, header: &Header, Ancestry) -> EpochChange;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Special "no-op" verifier for stateless, epoch-less engines.
|
|
||||||
pub struct NoOp;
|
|
||||||
|
|
||||||
impl EpochVerifier for NoOp {
|
|
||||||
fn epoch_number(&self) -> u64 { 0 }
|
|
||||||
fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
|
|
||||||
}
|
|
@ -24,16 +24,14 @@ use block::ExecutedBlock;
|
|||||||
/// An engine which does not provide any consensus mechanism, just seals blocks internally.
|
/// An engine which does not provide any consensus mechanism, just seals blocks internally.
|
||||||
pub struct InstantSeal {
|
pub struct InstantSeal {
|
||||||
params: CommonParams,
|
params: CommonParams,
|
||||||
registrar: Address,
|
|
||||||
builtins: BTreeMap<Address, Builtin>,
|
builtins: BTreeMap<Address, Builtin>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstantSeal {
|
impl InstantSeal {
|
||||||
/// Returns new instance of InstantSeal with default VM Factory
|
/// Returns new instance of InstantSeal with default VM Factory
|
||||||
pub fn new(params: CommonParams, registrar: Address, builtins: BTreeMap<Address, Builtin>) -> Self {
|
pub fn new(params: CommonParams, builtins: BTreeMap<Address, Builtin>) -> Self {
|
||||||
InstantSeal {
|
InstantSeal {
|
||||||
params: params,
|
params: params,
|
||||||
registrar: registrar,
|
|
||||||
builtins: builtins,
|
builtins: builtins,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +47,7 @@ impl Engine for InstantSeal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn additional_params(&self) -> HashMap<String, String> {
|
fn additional_params(&self) -> HashMap<String, String> {
|
||||||
hash_map!["registrar".to_owned() => self.registrar.hex()]
|
hash_map!["registrar".to_owned() => self.params().registrar.hex()]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn builtins(&self) -> &BTreeMap<Address, Builtin> {
|
fn builtins(&self) -> &BTreeMap<Address, Builtin> {
|
||||||
|
@ -43,15 +43,13 @@ use account_provider::AccountProvider;
|
|||||||
use block::ExecutedBlock;
|
use block::ExecutedBlock;
|
||||||
use builtin::Builtin;
|
use builtin::Builtin;
|
||||||
use client::Client;
|
use client::Client;
|
||||||
use evm::env_info::{EnvInfo, LastHashes};
|
use vm::{EnvInfo, LastHashes, Schedule, CreateContractAddress};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use evm::Schedule;
|
|
||||||
use header::{Header, BlockNumber};
|
use header::{Header, BlockNumber};
|
||||||
use receipt::Receipt;
|
use receipt::Receipt;
|
||||||
use snapshot::SnapshotComponents;
|
use snapshot::SnapshotComponents;
|
||||||
use spec::CommonParams;
|
use spec::CommonParams;
|
||||||
use transaction::{UnverifiedTransaction, SignedTransaction};
|
use transaction::{UnverifiedTransaction, SignedTransaction};
|
||||||
use evm::CreateContractAddress;
|
|
||||||
|
|
||||||
use ethkey::Signature;
|
use ethkey::Signature;
|
||||||
use util::*;
|
use util::*;
|
||||||
@ -394,12 +392,10 @@ pub trait Engine : Sync + Send {
|
|||||||
/// Common engine utilities
|
/// Common engine utilities
|
||||||
pub mod common {
|
pub mod common {
|
||||||
use block::ExecutedBlock;
|
use block::ExecutedBlock;
|
||||||
use evm::env_info::{EnvInfo, LastHashes};
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use transaction::SYSTEM_ADDRESS;
|
use transaction::SYSTEM_ADDRESS;
|
||||||
use executive::Executive;
|
use executive::Executive;
|
||||||
use evm::CallType;
|
use vm::{CallType, ActionParams, ActionValue, EnvInfo, LastHashes};
|
||||||
use evm::action_params::{ActionParams, ActionValue};
|
|
||||||
use trace::{NoopTracer, NoopVMTracer};
|
use trace::{NoopTracer, NoopVMTracer};
|
||||||
use state::Substate;
|
use state::Substate;
|
||||||
|
|
||||||
|
@ -33,15 +33,15 @@ use error::{Error, BlockError};
|
|||||||
use header::{Header, BlockNumber};
|
use header::{Header, BlockNumber};
|
||||||
use builtin::Builtin;
|
use builtin::Builtin;
|
||||||
use rlp::UntrustedRlp;
|
use rlp::UntrustedRlp;
|
||||||
use ethkey::{recover, public_to_address, Signature};
|
use ethkey::{Message, public_to_address, recover, Signature};
|
||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
use block::*;
|
use block::*;
|
||||||
use spec::CommonParams;
|
use spec::CommonParams;
|
||||||
use engines::{Engine, Seal, EngineError};
|
use engines::{Engine, Seal, EngineError, ConstructedVerifier};
|
||||||
use state::CleanupMode;
|
use state::CleanupMode;
|
||||||
use io::IoService;
|
use io::IoService;
|
||||||
use super::signer::EngineSigner;
|
use super::signer::EngineSigner;
|
||||||
use super::validator_set::ValidatorSet;
|
use super::validator_set::{ValidatorSet, SimpleList};
|
||||||
use super::transition::TransitionHandler;
|
use super::transition::TransitionHandler;
|
||||||
use super::vote_collector::VoteCollector;
|
use super::vote_collector::VoteCollector;
|
||||||
use self::message::*;
|
use self::message::*;
|
||||||
@ -71,12 +71,9 @@ pub type BlockHash = H256;
|
|||||||
/// Engine using `Tendermint` consensus algorithm, suitable for EVM chain.
|
/// Engine using `Tendermint` consensus algorithm, suitable for EVM chain.
|
||||||
pub struct Tendermint {
|
pub struct Tendermint {
|
||||||
params: CommonParams,
|
params: CommonParams,
|
||||||
gas_limit_bound_divisor: U256,
|
|
||||||
builtins: BTreeMap<Address, Builtin>,
|
builtins: BTreeMap<Address, Builtin>,
|
||||||
step_service: IoService<Step>,
|
step_service: IoService<Step>,
|
||||||
client: RwLock<Option<Weak<EngineClient>>>,
|
client: RwLock<Option<Weak<EngineClient>>>,
|
||||||
block_reward: U256,
|
|
||||||
registrar: Address,
|
|
||||||
/// Blockchain height.
|
/// Blockchain height.
|
||||||
height: AtomicUsize,
|
height: AtomicUsize,
|
||||||
/// Consensus view.
|
/// Consensus view.
|
||||||
@ -101,18 +98,74 @@ pub struct Tendermint {
|
|||||||
validators: Box<ValidatorSet>,
|
validators: Box<ValidatorSet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct EpochVerifier<F>
|
||||||
|
where F: Fn(&Signature, &Message) -> Result<Address, Error> + Send + Sync
|
||||||
|
{
|
||||||
|
subchain_validators: SimpleList,
|
||||||
|
recover: F
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <F> super::EpochVerifier for EpochVerifier<F>
|
||||||
|
where F: Fn(&Signature, &Message) -> Result<Address, Error> + Send + Sync
|
||||||
|
{
|
||||||
|
fn verify_light(&self, header: &Header) -> Result<(), Error> {
|
||||||
|
let message = header.bare_hash();
|
||||||
|
|
||||||
|
let mut addresses = HashSet::new();
|
||||||
|
let ref header_signatures_field = header.seal().get(2).ok_or(BlockError::InvalidSeal)?;
|
||||||
|
for rlp in UntrustedRlp::new(header_signatures_field).iter() {
|
||||||
|
let signature: H520 = rlp.as_val()?;
|
||||||
|
let address = (self.recover)(&signature.into(), &message)?;
|
||||||
|
|
||||||
|
if !self.subchain_validators.contains(header.parent_hash(), &address) {
|
||||||
|
return Err(EngineError::NotAuthorized(address.to_owned()).into());
|
||||||
|
}
|
||||||
|
addresses.insert(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
let n = addresses.len();
|
||||||
|
let threshold = self.subchain_validators.len() * 2/3;
|
||||||
|
if n > threshold {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(EngineError::BadSealFieldSize(OutOfBounds {
|
||||||
|
min: Some(threshold),
|
||||||
|
max: None,
|
||||||
|
found: n
|
||||||
|
}).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_finality_proof(&self, proof: &[u8]) -> Option<Vec<H256>> {
|
||||||
|
let header: Header = ::rlp::decode(proof);
|
||||||
|
self.verify_light(&header).ok().map(|_| vec![header.hash()])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn combine_proofs(signal_number: BlockNumber, set_proof: &[u8], finality_proof: &[u8]) -> Vec<u8> {
|
||||||
|
let mut stream = ::rlp::RlpStream::new_list(3);
|
||||||
|
stream.append(&signal_number).append(&set_proof).append(&finality_proof);
|
||||||
|
stream.out()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn destructure_proofs(combined: &[u8]) -> Result<(BlockNumber, &[u8], &[u8]), Error> {
|
||||||
|
let rlp = UntrustedRlp::new(combined);
|
||||||
|
Ok((
|
||||||
|
rlp.at(0)?.as_val()?,
|
||||||
|
rlp.at(1)?.data()?,
|
||||||
|
rlp.at(2)?.data()?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
impl Tendermint {
|
impl Tendermint {
|
||||||
/// Create a new instance of Tendermint engine
|
/// Create a new instance of Tendermint engine
|
||||||
pub fn new(params: CommonParams, our_params: TendermintParams, builtins: BTreeMap<Address, Builtin>) -> Result<Arc<Self>, Error> {
|
pub fn new(params: CommonParams, our_params: TendermintParams, builtins: BTreeMap<Address, Builtin>) -> Result<Arc<Self>, Error> {
|
||||||
let engine = Arc::new(
|
let engine = Arc::new(
|
||||||
Tendermint {
|
Tendermint {
|
||||||
params: params,
|
params: params,
|
||||||
gas_limit_bound_divisor: our_params.gas_limit_bound_divisor,
|
|
||||||
builtins: builtins,
|
builtins: builtins,
|
||||||
client: RwLock::new(None),
|
client: RwLock::new(None),
|
||||||
step_service: IoService::<Step>::start()?,
|
step_service: IoService::<Step>::start()?,
|
||||||
block_reward: our_params.block_reward,
|
|
||||||
registrar: our_params.registrar,
|
|
||||||
height: AtomicUsize::new(1),
|
height: AtomicUsize::new(1),
|
||||||
view: AtomicUsize::new(0),
|
view: AtomicUsize::new(0),
|
||||||
step: RwLock::new(Step::Propose),
|
step: RwLock::new(Step::Propose),
|
||||||
@ -387,7 +440,9 @@ impl Engine for Tendermint {
|
|||||||
|
|
||||||
fn params(&self) -> &CommonParams { &self.params }
|
fn params(&self) -> &CommonParams { &self.params }
|
||||||
|
|
||||||
fn additional_params(&self) -> HashMap<String, String> { hash_map!["registrar".to_owned() => self.registrar.hex()] }
|
fn additional_params(&self) -> HashMap<String, String> {
|
||||||
|
hash_map!["registrar".to_owned() => self.params().registrar.hex()]
|
||||||
|
}
|
||||||
|
|
||||||
fn builtins(&self) -> &BTreeMap<Address, Builtin> { &self.builtins }
|
fn builtins(&self) -> &BTreeMap<Address, Builtin> { &self.builtins }
|
||||||
|
|
||||||
@ -412,7 +467,7 @@ impl Engine for Tendermint {
|
|||||||
header.set_difficulty(new_difficulty);
|
header.set_difficulty(new_difficulty);
|
||||||
header.set_gas_limit({
|
header.set_gas_limit({
|
||||||
let gas_limit = parent.gas_limit().clone();
|
let gas_limit = parent.gas_limit().clone();
|
||||||
let bound_divisor = self.gas_limit_bound_divisor;
|
let bound_divisor = self.params().gas_limit_bound_divisor;
|
||||||
if gas_limit < gas_floor_target {
|
if gas_limit < gas_floor_target {
|
||||||
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
|
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
|
||||||
} else {
|
} else {
|
||||||
@ -427,6 +482,9 @@ impl Engine for Tendermint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to seal generate a proposal seal.
|
/// Attempt to seal generate a proposal seal.
|
||||||
|
///
|
||||||
|
/// This operation is synchronous and may (quite reasonably) not be available, in which case
|
||||||
|
/// `Seal::None` will be returned.
|
||||||
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
||||||
let header = block.header();
|
let header = block.header();
|
||||||
let author = header.author();
|
let author = header.author();
|
||||||
@ -483,7 +541,8 @@ impl Engine for Tendermint {
|
|||||||
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error>{
|
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error>{
|
||||||
let fields = block.fields_mut();
|
let fields = block.fields_mut();
|
||||||
// Bestow block reward
|
// Bestow block reward
|
||||||
let res = fields.state.add_balance(fields.header.author(), &self.block_reward, CleanupMode::NoEmpty)
|
let reward = self.params().block_reward;
|
||||||
|
let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty)
|
||||||
.map_err(::error::Error::from)
|
.map_err(::error::Error::from)
|
||||||
.and_then(|_| fields.state.commit());
|
.and_then(|_| fields.state.commit());
|
||||||
// Commit state so that we can actually figure out the state root.
|
// Commit state so that we can actually figure out the state root.
|
||||||
@ -555,7 +614,7 @@ impl Engine for Tendermint {
|
|||||||
self.check_above_threshold(origins.len())?
|
self.check_above_threshold(origins.len())?
|
||||||
}
|
}
|
||||||
|
|
||||||
let gas_limit_divisor = self.gas_limit_bound_divisor;
|
let gas_limit_divisor = self.params().gas_limit_bound_divisor;
|
||||||
let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
|
let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
|
||||||
let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor;
|
let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor;
|
||||||
if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas {
|
if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas {
|
||||||
@ -566,6 +625,57 @@ impl Engine for Tendermint {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn signals_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||||
|
-> super::EpochChange
|
||||||
|
{
|
||||||
|
let first = header.number() == 0;
|
||||||
|
self.validators.signals_epoch_end(first, header, block, receipts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_epoch_end(
|
||||||
|
&self,
|
||||||
|
chain_head: &Header,
|
||||||
|
_chain: &super::Headers,
|
||||||
|
transition_store: &super::PendingTransitionStore,
|
||||||
|
) -> Option<Vec<u8>> {
|
||||||
|
let first = chain_head.number() == 0;
|
||||||
|
|
||||||
|
if let Some(change) = self.validators.is_epoch_end(first, chain_head) {
|
||||||
|
return Some(change)
|
||||||
|
} else if let Some(pending) = transition_store(chain_head.hash()) {
|
||||||
|
let signal_number = chain_head.number();
|
||||||
|
let finality_proof = ::rlp::encode(chain_head);
|
||||||
|
return Some(combine_proofs(signal_number, &pending.proof, &finality_proof))
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn epoch_verifier<'a>(&self, _header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a> {
|
||||||
|
let (signal_number, set_proof, finality_proof) = match destructure_proofs(proof) {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(e) => return ConstructedVerifier::Err(e),
|
||||||
|
};
|
||||||
|
|
||||||
|
let first = signal_number == 0;
|
||||||
|
match self.validators.epoch_set(first, self, signal_number, set_proof) {
|
||||||
|
Ok((list, finalize)) => {
|
||||||
|
let verifier = Box::new(EpochVerifier {
|
||||||
|
subchain_validators: list,
|
||||||
|
recover: |signature: &Signature, message: &Message| {
|
||||||
|
Ok(public_to_address(&::ethkey::recover(&signature, &message)?))
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
match finalize {
|
||||||
|
Some(finalize) => ConstructedVerifier::Unconfirmed(verifier, finality_proof, finalize),
|
||||||
|
None => ConstructedVerifier::Trusted(verifier),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => ConstructedVerifier::Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) {
|
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) {
|
||||||
{
|
{
|
||||||
self.signer.write().set(ap, address, password);
|
self.signer.write().set(ap, address, password);
|
||||||
@ -577,6 +687,10 @@ impl Engine for Tendermint {
|
|||||||
self.signer.read().sign(hash).map_err(Into::into)
|
self.signer.read().sign(hash).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> {
|
||||||
|
Some(Box::new(::snapshot::PoaSnapshot))
|
||||||
|
}
|
||||||
|
|
||||||
fn stop(&self) {
|
fn stop(&self) {
|
||||||
self.step_service.stop()
|
self.step_service.stop()
|
||||||
}
|
}
|
||||||
@ -665,6 +779,7 @@ mod tests {
|
|||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use engines::{Engine, EngineError, Seal};
|
use engines::{Engine, EngineError, Seal};
|
||||||
|
use engines::epoch::EpochVerifier;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Accounts inserted with "0" and "1" are validators. First proposer is "0".
|
/// Accounts inserted with "0" and "1" are validators. First proposer is "0".
|
||||||
@ -949,4 +1064,76 @@ mod tests {
|
|||||||
vote(engine, |mh| tap.sign(v0, None, mh).map(H520::from), h, r, Step::Precommit, proposal);
|
vote(engine, |mh| tap.sign(v0, None, mh).map(H520::from), h, r, Step::Precommit, proposal);
|
||||||
assert_eq!(client.chain_info().best_block_number, 1);
|
assert_eq!(client.chain_info().best_block_number, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn epoch_verifier_verify_light() {
|
||||||
|
use ethkey::Error as EthkeyError;
|
||||||
|
|
||||||
|
let (spec, tap) = setup();
|
||||||
|
let engine = spec.engine;
|
||||||
|
|
||||||
|
let mut parent_header: Header = Header::default();
|
||||||
|
parent_header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||||
|
|
||||||
|
let mut header = Header::default();
|
||||||
|
header.set_number(2);
|
||||||
|
header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||||
|
let proposer = insert_and_unlock(&tap, "1");
|
||||||
|
header.set_author(proposer);
|
||||||
|
let mut seal = proposal_seal(&tap, &header, 0);
|
||||||
|
|
||||||
|
let vote_info = message_info_rlp(&VoteStep::new(2, 0, Step::Precommit), Some(header.bare_hash()));
|
||||||
|
let signature1 = tap.sign(proposer, None, vote_info.sha3()).unwrap();
|
||||||
|
|
||||||
|
let voter = insert_and_unlock(&tap, "0");
|
||||||
|
let signature0 = tap.sign(voter, None, vote_info.sha3()).unwrap();
|
||||||
|
|
||||||
|
seal[1] = ::rlp::NULL_RLP.to_vec();
|
||||||
|
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec();
|
||||||
|
header.set_seal(seal.clone());
|
||||||
|
|
||||||
|
let epoch_verifier = super::EpochVerifier {
|
||||||
|
subchain_validators: SimpleList::new(vec![proposer.clone(), voter.clone()]),
|
||||||
|
recover: {
|
||||||
|
let signature1 = signature1.clone();
|
||||||
|
let signature0 = signature0.clone();
|
||||||
|
let proposer = proposer.clone();
|
||||||
|
let voter = voter.clone();
|
||||||
|
move |s: &Signature, _: &Message| {
|
||||||
|
if *s == signature1 {
|
||||||
|
Ok(proposer)
|
||||||
|
} else if *s == signature0 {
|
||||||
|
Ok(voter)
|
||||||
|
} else {
|
||||||
|
Err(Error::Ethkey(EthkeyError::InvalidSignature))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// One good signature is not enough.
|
||||||
|
match epoch_verifier.verify_light(&header) {
|
||||||
|
Err(Error::Engine(EngineError::BadSealFieldSize(_))) => {},
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).into_vec();
|
||||||
|
header.set_seal(seal.clone());
|
||||||
|
|
||||||
|
assert!(epoch_verifier.verify_light(&header).is_ok());
|
||||||
|
|
||||||
|
let bad_voter = insert_and_unlock(&tap, "101");
|
||||||
|
let bad_signature = tap.sign(bad_voter, None, vote_info.sha3()).unwrap();
|
||||||
|
|
||||||
|
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec();
|
||||||
|
header.set_seal(seal);
|
||||||
|
|
||||||
|
// One good and one bad signature.
|
||||||
|
match epoch_verifier.verify_light(&header) {
|
||||||
|
Err(Error::Ethkey(EthkeyError::InvalidSignature)) => {},
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
engine.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
//! Tendermint specific parameters.
|
//! Tendermint specific parameters.
|
||||||
|
|
||||||
use ethjson;
|
use ethjson;
|
||||||
use util::{U256, Address};
|
|
||||||
use time::Duration;
|
use time::Duration;
|
||||||
use super::super::validator_set::{ValidatorSet, new_validator_set};
|
use super::super::validator_set::{ValidatorSet, new_validator_set};
|
||||||
use super::super::transition::Timeouts;
|
use super::super::transition::Timeouts;
|
||||||
@ -25,16 +24,10 @@ use super::Step;
|
|||||||
|
|
||||||
/// `Tendermint` params.
|
/// `Tendermint` params.
|
||||||
pub struct TendermintParams {
|
pub struct TendermintParams {
|
||||||
/// Gas limit divisor.
|
|
||||||
pub gas_limit_bound_divisor: U256,
|
|
||||||
/// List of validators.
|
/// List of validators.
|
||||||
pub validators: Box<ValidatorSet>,
|
pub validators: Box<ValidatorSet>,
|
||||||
/// Timeout durations for different steps.
|
/// Timeout durations for different steps.
|
||||||
pub timeouts: TendermintTimeouts,
|
pub timeouts: TendermintTimeouts,
|
||||||
/// Block reward.
|
|
||||||
pub block_reward: U256,
|
|
||||||
/// Namereg contract address.
|
|
||||||
pub registrar: Address,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Base timeout of each step in ms.
|
/// Base timeout of each step in ms.
|
||||||
@ -81,7 +74,6 @@ impl From<ethjson::spec::TendermintParams> for TendermintParams {
|
|||||||
fn from(p: ethjson::spec::TendermintParams) -> Self {
|
fn from(p: ethjson::spec::TendermintParams) -> Self {
|
||||||
let dt = TendermintTimeouts::default();
|
let dt = TendermintTimeouts::default();
|
||||||
TendermintParams {
|
TendermintParams {
|
||||||
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
|
|
||||||
validators: new_validator_set(p.validators),
|
validators: new_validator_set(p.validators),
|
||||||
timeouts: TendermintTimeouts {
|
timeouts: TendermintTimeouts {
|
||||||
propose: p.timeout_propose.map_or(dt.propose, to_duration),
|
propose: p.timeout_propose.map_or(dt.propose, to_duration),
|
||||||
@ -89,8 +81,6 @@ impl From<ethjson::spec::TendermintParams> for TendermintParams {
|
|||||||
precommit: p.timeout_precommit.map_or(dt.precommit, to_duration),
|
precommit: p.timeout_precommit.map_or(dt.precommit, to_duration),
|
||||||
commit: p.timeout_commit.map_or(dt.commit, to_duration),
|
commit: p.timeout_commit.map_or(dt.commit, to_duration),
|
||||||
},
|
},
|
||||||
block_reward: p.block_reward.map_or_else(U256::zero, Into::into),
|
|
||||||
registrar: p.registrar.map_or_else(Address::new, Into::into),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
|||||||
let (old_header, state_items) = decode_first_proof(&rlp)?;
|
let (old_header, state_items) = decode_first_proof(&rlp)?;
|
||||||
let old_hash = old_header.hash();
|
let old_hash = old_header.hash();
|
||||||
|
|
||||||
let env_info = ::evm::env_info::EnvInfo {
|
let env_info = ::vm::EnvInfo {
|
||||||
number: old_header.number(),
|
number: old_header.number(),
|
||||||
author: *old_header.author(),
|
author: *old_header.author(),
|
||||||
difficulty: *old_header.difficulty(),
|
difficulty: *old_header.difficulty(),
|
||||||
|
@ -19,7 +19,7 @@ use ethash::{quick_get_difficulty, slow_get_seedhash, EthashManager};
|
|||||||
use util::*;
|
use util::*;
|
||||||
use block::*;
|
use block::*;
|
||||||
use builtin::Builtin;
|
use builtin::Builtin;
|
||||||
use evm::env_info::EnvInfo;
|
use vm::EnvInfo;
|
||||||
use error::{BlockError, Error, TransactionError};
|
use error::{BlockError, Error, TransactionError};
|
||||||
use header::{Header, BlockNumber};
|
use header::{Header, BlockNumber};
|
||||||
use state::CleanupMode;
|
use state::CleanupMode;
|
||||||
@ -29,7 +29,7 @@ use engines::{self, Engine};
|
|||||||
use evm::Schedule;
|
use evm::Schedule;
|
||||||
use ethjson;
|
use ethjson;
|
||||||
use rlp::{self, UntrustedRlp};
|
use rlp::{self, UntrustedRlp};
|
||||||
use evm::env_info::LastHashes;
|
use vm::LastHashes;
|
||||||
|
|
||||||
/// Parity tries to round block.gas_limit to multiple of this constant
|
/// Parity tries to round block.gas_limit to multiple of this constant
|
||||||
pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]);
|
pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]);
|
||||||
@ -41,8 +41,6 @@ const SNAPSHOT_BLOCKS: u64 = 30000;
|
|||||||
/// Ethash params.
|
/// Ethash params.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct EthashParams {
|
pub struct EthashParams {
|
||||||
/// Gas limit divisor.
|
|
||||||
pub gas_limit_bound_divisor: U256,
|
|
||||||
/// Minimum difficulty.
|
/// Minimum difficulty.
|
||||||
pub minimum_difficulty: U256,
|
pub minimum_difficulty: U256,
|
||||||
/// Difficulty bound divisor.
|
/// Difficulty bound divisor.
|
||||||
@ -53,10 +51,6 @@ pub struct EthashParams {
|
|||||||
pub metropolis_difficulty_increment_divisor: u64,
|
pub metropolis_difficulty_increment_divisor: u64,
|
||||||
/// Block duration.
|
/// Block duration.
|
||||||
pub duration_limit: u64,
|
pub duration_limit: u64,
|
||||||
/// Block reward.
|
|
||||||
pub block_reward: U256,
|
|
||||||
/// Namereg contract address.
|
|
||||||
pub registrar: Address,
|
|
||||||
/// Homestead transition block number.
|
/// Homestead transition block number.
|
||||||
pub homestead_transition: u64,
|
pub homestead_transition: u64,
|
||||||
/// DAO hard-fork transition block (X).
|
/// DAO hard-fork transition block (X).
|
||||||
@ -75,8 +69,6 @@ pub struct EthashParams {
|
|||||||
pub eip100b_transition: u64,
|
pub eip100b_transition: u64,
|
||||||
/// Number of first block where EIP-150 rules begin.
|
/// Number of first block where EIP-150 rules begin.
|
||||||
pub eip150_transition: u64,
|
pub eip150_transition: u64,
|
||||||
/// Number of first block where EIP-155 rules begin.
|
|
||||||
pub eip155_transition: u64,
|
|
||||||
/// Number of first block where EIP-160 rules begin.
|
/// Number of first block where EIP-160 rules begin.
|
||||||
pub eip160_transition: u64,
|
pub eip160_transition: u64,
|
||||||
/// Number of first block where EIP-161.abc begin.
|
/// Number of first block where EIP-161.abc begin.
|
||||||
@ -104,14 +96,11 @@ pub struct EthashParams {
|
|||||||
impl From<ethjson::spec::EthashParams> for EthashParams {
|
impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||||
fn from(p: ethjson::spec::EthashParams) -> Self {
|
fn from(p: ethjson::spec::EthashParams) -> Self {
|
||||||
EthashParams {
|
EthashParams {
|
||||||
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
|
|
||||||
minimum_difficulty: p.minimum_difficulty.into(),
|
minimum_difficulty: p.minimum_difficulty.into(),
|
||||||
difficulty_bound_divisor: p.difficulty_bound_divisor.into(),
|
difficulty_bound_divisor: p.difficulty_bound_divisor.into(),
|
||||||
difficulty_increment_divisor: p.difficulty_increment_divisor.map_or(10, Into::into),
|
difficulty_increment_divisor: p.difficulty_increment_divisor.map_or(10, Into::into),
|
||||||
metropolis_difficulty_increment_divisor: p.metropolis_difficulty_increment_divisor.map_or(9, Into::into),
|
metropolis_difficulty_increment_divisor: p.metropolis_difficulty_increment_divisor.map_or(9, Into::into),
|
||||||
duration_limit: p.duration_limit.map_or(0, Into::into),
|
duration_limit: p.duration_limit.map_or(0, Into::into),
|
||||||
block_reward: p.block_reward.into(),
|
|
||||||
registrar: p.registrar.map_or_else(Address::new, Into::into),
|
|
||||||
homestead_transition: p.homestead_transition.map_or(0, Into::into),
|
homestead_transition: p.homestead_transition.map_or(0, Into::into),
|
||||||
dao_hardfork_transition: p.dao_hardfork_transition.map_or(u64::max_value(), Into::into),
|
dao_hardfork_transition: p.dao_hardfork_transition.map_or(u64::max_value(), Into::into),
|
||||||
dao_hardfork_beneficiary: p.dao_hardfork_beneficiary.map_or_else(Address::new, Into::into),
|
dao_hardfork_beneficiary: p.dao_hardfork_beneficiary.map_or_else(Address::new, Into::into),
|
||||||
@ -121,7 +110,6 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
|||||||
bomb_defuse_transition: p.bomb_defuse_transition.map_or(u64::max_value(), Into::into),
|
bomb_defuse_transition: p.bomb_defuse_transition.map_or(u64::max_value(), Into::into),
|
||||||
eip100b_transition: p.eip100b_transition.map_or(u64::max_value(), Into::into),
|
eip100b_transition: p.eip100b_transition.map_or(u64::max_value(), Into::into),
|
||||||
eip150_transition: p.eip150_transition.map_or(0, Into::into),
|
eip150_transition: p.eip150_transition.map_or(0, Into::into),
|
||||||
eip155_transition: p.eip155_transition.map_or(0, Into::into),
|
|
||||||
eip160_transition: p.eip160_transition.map_or(0, Into::into),
|
eip160_transition: p.eip160_transition.map_or(0, Into::into),
|
||||||
eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into),
|
eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into),
|
||||||
eip161d_transition: p.eip161d_transition.map_or(u64::max_value(), Into::into),
|
eip161d_transition: p.eip161d_transition.map_or(u64::max_value(), Into::into),
|
||||||
@ -185,7 +173,7 @@ impl Engine for Arc<Ethash> {
|
|||||||
fn seal_fields(&self) -> usize { 2 }
|
fn seal_fields(&self) -> usize { 2 }
|
||||||
|
|
||||||
fn params(&self) -> &CommonParams { &self.params }
|
fn params(&self) -> &CommonParams { &self.params }
|
||||||
fn additional_params(&self) -> HashMap<String, String> { hash_map!["registrar".to_owned() => self.ethash_params.registrar.hex()] }
|
fn additional_params(&self) -> HashMap<String, String> { hash_map!["registrar".to_owned() => self.params().registrar.hex()] }
|
||||||
|
|
||||||
fn builtins(&self) -> &BTreeMap<Address, Builtin> {
|
fn builtins(&self) -> &BTreeMap<Address, Builtin> {
|
||||||
&self.builtins
|
&self.builtins
|
||||||
@ -216,7 +204,7 @@ impl Engine for Arc<Ethash> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signing_network_id(&self, env_info: &EnvInfo) -> Option<u64> {
|
fn signing_network_id(&self, env_info: &EnvInfo) -> Option<u64> {
|
||||||
if env_info.number >= self.ethash_params.eip155_transition {
|
if env_info.number >= self.params().eip155_transition {
|
||||||
Some(self.params().chain_id)
|
Some(self.params().chain_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -231,7 +219,7 @@ impl Engine for Arc<Ethash> {
|
|||||||
}
|
}
|
||||||
let gas_limit = {
|
let gas_limit = {
|
||||||
let gas_limit = parent.gas_limit().clone();
|
let gas_limit = parent.gas_limit().clone();
|
||||||
let bound_divisor = self.ethash_params.gas_limit_bound_divisor;
|
let bound_divisor = self.params().gas_limit_bound_divisor;
|
||||||
let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into();
|
let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into();
|
||||||
let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into();
|
let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into();
|
||||||
let gas_limit = if gas_limit < gas_floor_target {
|
let gas_limit = if gas_limit < gas_floor_target {
|
||||||
@ -284,7 +272,7 @@ impl Engine for Arc<Ethash> {
|
|||||||
/// Apply the block reward on finalisation of the block.
|
/// Apply the block reward on finalisation of the block.
|
||||||
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
|
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
|
||||||
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
|
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
|
||||||
let reward = self.ethash_params.block_reward;
|
let reward = self.params().block_reward;
|
||||||
let fields = block.fields_mut();
|
let fields = block.fields_mut();
|
||||||
let eras_rounds = self.ethash_params.ecip1017_era_rounds;
|
let eras_rounds = self.ethash_params.ecip1017_era_rounds;
|
||||||
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number());
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number());
|
||||||
@ -387,7 +375,7 @@ impl Engine for Arc<Ethash> {
|
|||||||
if header.difficulty() != &expected_difficulty {
|
if header.difficulty() != &expected_difficulty {
|
||||||
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: expected_difficulty, found: header.difficulty().clone() })))
|
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: expected_difficulty, found: header.difficulty().clone() })))
|
||||||
}
|
}
|
||||||
let gas_limit_divisor = self.ethash_params.gas_limit_bound_divisor;
|
let gas_limit_divisor = self.params().gas_limit_bound_divisor;
|
||||||
let parent_gas_limit = *parent.gas_limit();
|
let parent_gas_limit = *parent.gas_limit();
|
||||||
let min_gas = parent_gas_limit - parent_gas_limit / gas_limit_divisor;
|
let min_gas = parent_gas_limit - parent_gas_limit / gas_limit_divisor;
|
||||||
let max_gas = parent_gas_limit + parent_gas_limit / gas_limit_divisor;
|
let max_gas = parent_gas_limit + parent_gas_limit / gas_limit_divisor;
|
||||||
@ -406,7 +394,7 @@ impl Engine for Arc<Ethash> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let check_low_s = header.number() >= self.ethash_params.homestead_transition;
|
let check_low_s = header.number() >= self.ethash_params.homestead_transition;
|
||||||
let network_id = if header.number() >= self.ethash_params.eip155_transition { Some(self.params().chain_id) } else { None };
|
let network_id = if header.number() >= self.params().eip155_transition { Some(self.params().chain_id) } else { None };
|
||||||
t.verify_basic(check_low_s, network_id, false)?;
|
t.verify_basic(check_low_s, network_id, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -809,36 +797,32 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn has_valid_ecip1017_eras_block_reward() {
|
fn has_valid_ecip1017_eras_block_reward() {
|
||||||
let ethparams = EthashParams {
|
let eras_rounds = 5000000;
|
||||||
// see ethcore/res/ethereum/classic.json
|
|
||||||
ecip1017_era_rounds: 5000000,
|
let start_reward: U256 = "4563918244F40000".parse().unwrap();
|
||||||
block_reward: U256::from_str("4563918244F40000").unwrap(),
|
|
||||||
..get_default_ethash_params()
|
|
||||||
};
|
|
||||||
let eras_rounds = ethparams.ecip1017_era_rounds;
|
|
||||||
let reward = ethparams.block_reward;
|
|
||||||
let block_number = 0;
|
let block_number = 0;
|
||||||
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
|
||||||
assert_eq!(0, eras);
|
assert_eq!(0, eras);
|
||||||
assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward);
|
assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward);
|
||||||
let reward = ethparams.block_reward;
|
|
||||||
let block_number = 5000000;
|
let block_number = 5000000;
|
||||||
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
|
||||||
assert_eq!(0, eras);
|
assert_eq!(0, eras);
|
||||||
assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward);
|
assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward);
|
||||||
let reward = ethparams.block_reward;
|
|
||||||
let block_number = 10000000;
|
let block_number = 10000000;
|
||||||
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
|
||||||
assert_eq!(1, eras);
|
assert_eq!(1, eras);
|
||||||
assert_eq!(U256::from_str("3782DACE9D900000").unwrap(), reward);
|
assert_eq!(U256::from_str("3782DACE9D900000").unwrap(), reward);
|
||||||
let reward = ethparams.block_reward;
|
|
||||||
let block_number = 20000000;
|
let block_number = 20000000;
|
||||||
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
|
||||||
assert_eq!(3, eras);
|
assert_eq!(3, eras);
|
||||||
assert_eq!(U256::from_str("2386F26FC1000000").unwrap(), reward);
|
assert_eq!(U256::from_str("2386F26FC1000000").unwrap(), reward);
|
||||||
let reward = ethparams.block_reward;
|
|
||||||
let block_number = 80000000;
|
let block_number = 80000000;
|
||||||
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
|
||||||
assert_eq!(15, eras);
|
assert_eq!(15, eras);
|
||||||
assert_eq!(U256::from_str("271000000000000").unwrap(), reward);
|
assert_eq!(U256::from_str("271000000000000").unwrap(), reward);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! Transaction execution format module.
|
//! Transaction execution format module.
|
||||||
|
|
||||||
use util::{Bytes, U256, Address, U512, trie};
|
use util::{Bytes, U256, Address, U512, trie};
|
||||||
use evm;
|
use vm;
|
||||||
use trace::{VMTrace, FlatTrace};
|
use trace::{VMTrace, FlatTrace};
|
||||||
use log_entry::LogEntry;
|
use log_entry::LogEntry;
|
||||||
use state_diff::StateDiff;
|
use state_diff::StateDiff;
|
||||||
@ -28,7 +28,7 @@ use std::fmt;
|
|||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Executed {
|
pub struct Executed {
|
||||||
/// True if the outer call/create resulted in an exceptional exit.
|
/// True if the outer call/create resulted in an exceptional exit.
|
||||||
pub exception: Option<evm::Error>,
|
pub exception: Option<vm::Error>,
|
||||||
|
|
||||||
/// Gas paid up front for execution of transaction.
|
/// Gas paid up front for execution of transaction.
|
||||||
pub gas: U256,
|
pub gas: U256,
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
//! Transaction Execution environment.
|
//! Transaction Execution environment.
|
||||||
use util::*;
|
use util::*;
|
||||||
use evm::action_params::{ActionParams, ActionValue};
|
|
||||||
use state::{Backend as StateBackend, State, Substate, CleanupMode};
|
use state::{Backend as StateBackend, State, Substate, CleanupMode};
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
use evm::CallType;
|
use vm::EnvInfo;
|
||||||
use evm::env_info::EnvInfo;
|
|
||||||
use error::ExecutionError;
|
use error::ExecutionError;
|
||||||
use evm::{self, wasm, Factory, Ext, Finalize, CreateContractAddress, FinalizationResult, ReturnData, CleanDustMode};
|
use evm::{CallType, Factory, Finalize, FinalizationResult};
|
||||||
|
use vm::{self, Ext, CreateContractAddress, ReturnData, CleanDustMode, ActionParams, ActionValue};
|
||||||
|
use wasm;
|
||||||
use externalities::*;
|
use externalities::*;
|
||||||
use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer};
|
use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer};
|
||||||
use transaction::{Action, SignedTransaction};
|
use transaction::{Action, SignedTransaction};
|
||||||
@ -75,7 +75,7 @@ pub struct TransactOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn executor<E>(engine: &E, vm_factory: &Factory, params: &ActionParams)
|
pub fn executor<E>(engine: &E, vm_factory: &Factory, params: &ActionParams)
|
||||||
-> Box<evm::Evm> where E: Engine + ?Sized
|
-> Box<vm::Vm> where E: Engine + ?Sized
|
||||||
{
|
{
|
||||||
if engine.supports_wasm() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
|
if engine.supports_wasm() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
|
||||||
Box::new(
|
Box::new(
|
||||||
@ -269,7 +269,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
output_policy: OutputPolicy,
|
output_policy: OutputPolicy,
|
||||||
tracer: &mut T,
|
tracer: &mut T,
|
||||||
vm_tracer: &mut V
|
vm_tracer: &mut V
|
||||||
) -> evm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
|
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
|
||||||
|
|
||||||
let depth_threshold = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get() / STACK_SIZE_PER_DEPTH);
|
let depth_threshold = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get() / STACK_SIZE_PER_DEPTH);
|
||||||
let static_call = params.call_type == CallType::StaticCall;
|
let static_call = params.call_type == CallType::StaticCall;
|
||||||
@ -299,7 +299,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
/// Calls contract function with given contract params.
|
/// Calls contract function with given contract params.
|
||||||
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
|
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
|
||||||
/// Modifies the substate and the output.
|
/// Modifies the substate and the output.
|
||||||
/// Returns either gas_left or `evm::Error`.
|
/// Returns either gas_left or `vm::Error`.
|
||||||
pub fn call<T, V>(
|
pub fn call<T, V>(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: ActionParams,
|
params: ActionParams,
|
||||||
@ -307,14 +307,14 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
mut output: BytesRef,
|
mut output: BytesRef,
|
||||||
tracer: &mut T,
|
tracer: &mut T,
|
||||||
vm_tracer: &mut V
|
vm_tracer: &mut V
|
||||||
) -> evm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
|
) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
|
||||||
|
|
||||||
trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);
|
trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);
|
||||||
if (params.call_type == CallType::StaticCall ||
|
if (params.call_type == CallType::StaticCall ||
|
||||||
((params.call_type == CallType::Call || params.call_type == CallType::DelegateCall) &&
|
((params.call_type == CallType::Call || params.call_type == CallType::DelegateCall) &&
|
||||||
self.static_flag))
|
self.static_flag))
|
||||||
&& params.value.value() > 0.into() {
|
&& params.value.value() > 0.into() {
|
||||||
return Err(evm::Error::MutableCallInStaticContext);
|
return Err(vm::Error::MutableCallInStaticContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// backup used in case of running out of gas
|
// backup used in case of running out of gas
|
||||||
@ -344,7 +344,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
if cost <= params.gas {
|
if cost <= params.gas {
|
||||||
if let Err(e) = builtin.execute(data, &mut output) {
|
if let Err(e) = builtin.execute(data, &mut output) {
|
||||||
self.state.revert_to_checkpoint();
|
self.state.revert_to_checkpoint();
|
||||||
let evm_err: evm::evm::Error = e.into();
|
let evm_err: vm::Error = e.into();
|
||||||
tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into());
|
tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into());
|
||||||
Err(evm_err)
|
Err(evm_err)
|
||||||
} else {
|
} else {
|
||||||
@ -371,9 +371,9 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
// just drain the whole gas
|
// just drain the whole gas
|
||||||
self.state.revert_to_checkpoint();
|
self.state.revert_to_checkpoint();
|
||||||
|
|
||||||
tracer.trace_failed_call(trace_info, vec![], evm::Error::OutOfGas.into());
|
tracer.trace_failed_call(trace_info, vec![], vm::Error::OutOfGas.into());
|
||||||
|
|
||||||
Err(evm::Error::OutOfGas)
|
Err(vm::Error::OutOfGas)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let trace_info = tracer.prepare_trace_call(¶ms);
|
let trace_info = tracer.prepare_trace_call(¶ms);
|
||||||
@ -432,17 +432,17 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
substate: &mut Substate,
|
substate: &mut Substate,
|
||||||
tracer: &mut T,
|
tracer: &mut T,
|
||||||
vm_tracer: &mut V,
|
vm_tracer: &mut V,
|
||||||
) -> evm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
|
) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
|
||||||
|
|
||||||
let scheme = self.engine.create_address_scheme(self.info.number);
|
let scheme = self.engine.create_address_scheme(self.info.number);
|
||||||
if scheme != CreateContractAddress::FromSenderAndNonce && self.state.exists_and_has_code(¶ms.address)? {
|
if scheme != CreateContractAddress::FromSenderAndNonce && self.state.exists_and_has_code(¶ms.address)? {
|
||||||
return Err(evm::Error::OutOfGas);
|
return Err(vm::Error::OutOfGas);
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.call_type == CallType::StaticCall || self.static_flag {
|
if params.call_type == CallType::StaticCall || self.static_flag {
|
||||||
let trace_info = tracer.prepare_trace_create(¶ms);
|
let trace_info = tracer.prepare_trace_create(¶ms);
|
||||||
tracer.trace_failed_create(trace_info, vec![], evm::Error::MutableCallInStaticContext.into());
|
tracer.trace_failed_create(trace_info, vec![], vm::Error::MutableCallInStaticContext.into());
|
||||||
return Err(evm::Error::MutableCallInStaticContext);
|
return Err(vm::Error::MutableCallInStaticContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// backup used in case of running out of gas
|
// backup used in case of running out of gas
|
||||||
@ -496,7 +496,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
t: &SignedTransaction,
|
t: &SignedTransaction,
|
||||||
mut substate: Substate,
|
mut substate: Substate,
|
||||||
result: evm::Result<(U256, ReturnData)>,
|
result: vm::Result<(U256, ReturnData)>,
|
||||||
output: Bytes,
|
output: Bytes,
|
||||||
trace: Vec<FlatTrace>,
|
trace: Vec<FlatTrace>,
|
||||||
vm_trace: Option<VMTrace>
|
vm_trace: Option<VMTrace>
|
||||||
@ -538,7 +538,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
self.state.kill_garbage(&substate.touched, schedule.kill_empty, &min_balance, schedule.kill_dust == CleanDustMode::WithCodeAndStorage)?;
|
self.state.kill_garbage(&substate.touched, schedule.kill_empty, &min_balance, schedule.kill_dust == CleanDustMode::WithCodeAndStorage)?;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Err(evm::Error::Internal(msg)) => Err(ExecutionError::Internal(msg)),
|
Err(vm::Error::Internal(msg)) => Err(ExecutionError::Internal(msg)),
|
||||||
Err(exception) => {
|
Err(exception) => {
|
||||||
Ok(Executed {
|
Ok(Executed {
|
||||||
exception: Some(exception),
|
exception: Some(exception),
|
||||||
@ -572,20 +572,20 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enact_result(&mut self, result: &evm::Result<FinalizationResult>, substate: &mut Substate, un_substate: Substate) {
|
fn enact_result(&mut self, result: &vm::Result<FinalizationResult>, substate: &mut Substate, un_substate: Substate) {
|
||||||
match *result {
|
match *result {
|
||||||
Err(evm::Error::OutOfGas)
|
Err(vm::Error::OutOfGas)
|
||||||
| Err(evm::Error::BadJumpDestination {..})
|
| Err(vm::Error::BadJumpDestination {..})
|
||||||
| Err(evm::Error::BadInstruction {.. })
|
| Err(vm::Error::BadInstruction {.. })
|
||||||
| Err(evm::Error::StackUnderflow {..})
|
| Err(vm::Error::StackUnderflow {..})
|
||||||
| Err(evm::Error::BuiltIn {..})
|
| Err(vm::Error::BuiltIn {..})
|
||||||
| Err(evm::Error::Wasm {..})
|
| Err(vm::Error::Wasm {..})
|
||||||
| Err(evm::Error::OutOfStack {..})
|
| Err(vm::Error::OutOfStack {..})
|
||||||
| Err(evm::Error::MutableCallInStaticContext)
|
| Err(vm::Error::MutableCallInStaticContext)
|
||||||
| Ok(FinalizationResult { apply_state: false, .. }) => {
|
| Ok(FinalizationResult { apply_state: false, .. }) => {
|
||||||
self.state.revert_to_checkpoint();
|
self.state.revert_to_checkpoint();
|
||||||
},
|
},
|
||||||
Ok(_) | Err(evm::Error::Internal(_)) => {
|
Ok(_) | Err(vm::Error::Internal(_)) => {
|
||||||
self.state.discard_checkpoint();
|
self.state.discard_checkpoint();
|
||||||
substate.accrue(un_substate);
|
substate.accrue(un_substate);
|
||||||
}
|
}
|
||||||
@ -602,9 +602,8 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use util::{H256, U256, U512, Address, FromStr};
|
use util::{H256, U256, U512, Address, FromStr};
|
||||||
use util::bytes::BytesRef;
|
use util::bytes::BytesRef;
|
||||||
use evm::action_params::{ActionParams, ActionValue};
|
use vm::{ActionParams, ActionValue, CallType, EnvInfo, CreateContractAddress};
|
||||||
use evm::env_info::EnvInfo;
|
use evm::{Factory, VMType};
|
||||||
use evm::{Factory, VMType, CreateContractAddress};
|
|
||||||
use error::ExecutionError;
|
use error::ExecutionError;
|
||||||
use state::{Substate, CleanupMode};
|
use state::{Substate, CleanupMode};
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
@ -613,8 +612,6 @@ mod tests {
|
|||||||
use trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, VMTracer, NoopVMTracer, ExecutiveVMTracer};
|
use trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, VMTracer, NoopVMTracer, ExecutiveVMTracer};
|
||||||
use transaction::{Action, Transaction};
|
use transaction::{Action, Transaction};
|
||||||
|
|
||||||
use evm::CallType;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_contract_address() {
|
fn test_contract_address() {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
|
@ -16,13 +16,14 @@
|
|||||||
|
|
||||||
//! Transaction Execution environment.
|
//! Transaction Execution environment.
|
||||||
use util::*;
|
use util::*;
|
||||||
use evm::action_params::{ActionParams, ActionValue};
|
|
||||||
use state::{Backend as StateBackend, State, Substate, CleanupMode};
|
use state::{Backend as StateBackend, State, Substate, CleanupMode};
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
use evm::env_info::EnvInfo;
|
|
||||||
use executive::*;
|
use executive::*;
|
||||||
use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData};
|
use vm::{
|
||||||
use evm::CallType;
|
self, ActionParams, ActionValue, EnvInfo, CallType, Schedule,
|
||||||
|
Ext, ContractCreateResult, MessageCallResult, CreateContractAddress,
|
||||||
|
ReturnData
|
||||||
|
};
|
||||||
use transaction::UNSIGNED_SENDER;
|
use transaction::UNSIGNED_SENDER;
|
||||||
use trace::{Tracer, VMTracer};
|
use trace::{Tracer, VMTracer};
|
||||||
|
|
||||||
@ -109,31 +110,31 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E>
|
|||||||
impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
|
impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
|
||||||
where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized
|
where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized
|
||||||
{
|
{
|
||||||
fn storage_at(&self, key: &H256) -> evm::Result<H256> {
|
fn storage_at(&self, key: &H256) -> vm::Result<H256> {
|
||||||
self.state.storage_at(&self.origin_info.address, key).map_err(Into::into)
|
self.state.storage_at(&self.origin_info.address, key).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> {
|
fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> {
|
||||||
if self.static_flag {
|
if self.static_flag {
|
||||||
Err(evm::Error::MutableCallInStaticContext)
|
Err(vm::Error::MutableCallInStaticContext)
|
||||||
} else {
|
} else {
|
||||||
self.state.set_storage(&self.origin_info.address, key, value).map_err(Into::into)
|
self.state.set_storage(&self.origin_info.address, key, value).map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exists(&self, address: &Address) -> evm::Result<bool> {
|
fn exists(&self, address: &Address) -> vm::Result<bool> {
|
||||||
self.state.exists(address).map_err(Into::into)
|
self.state.exists(address).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exists_and_not_null(&self, address: &Address) -> evm::Result<bool> {
|
fn exists_and_not_null(&self, address: &Address) -> vm::Result<bool> {
|
||||||
self.state.exists_and_not_null(address).map_err(Into::into)
|
self.state.exists_and_not_null(address).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn origin_balance(&self) -> evm::Result<U256> {
|
fn origin_balance(&self) -> vm::Result<U256> {
|
||||||
self.balance(&self.origin_info.address).map_err(Into::into)
|
self.balance(&self.origin_info.address).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn balance(&self, address: &Address) -> evm::Result<U256> {
|
fn balance(&self, address: &Address) -> vm::Result<U256> {
|
||||||
self.state.balance(address).map_err(Into::into)
|
self.state.balance(address).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,16 +275,16 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcode(&self, address: &Address) -> evm::Result<Arc<Bytes>> {
|
fn extcode(&self, address: &Address) -> vm::Result<Arc<Bytes>> {
|
||||||
Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![])))
|
Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![])))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcodesize(&self, address: &Address) -> evm::Result<usize> {
|
fn extcodesize(&self, address: &Address) -> vm::Result<usize> {
|
||||||
Ok(self.state.code_size(address)?.unwrap_or(0))
|
Ok(self.state.code_size(address)?.unwrap_or(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
||||||
fn ret(mut self, gas: &U256, data: &ReturnData) -> evm::Result<U256>
|
fn ret(mut self, gas: &U256, data: &ReturnData) -> vm::Result<U256>
|
||||||
where Self: Sized {
|
where Self: Sized {
|
||||||
let handle_copy = |to: &mut Option<&mut Bytes>| {
|
let handle_copy = |to: &mut Option<&mut Bytes>| {
|
||||||
to.as_mut().map(|b| **b = data.to_vec());
|
to.as_mut().map(|b| **b = data.to_vec());
|
||||||
@ -307,7 +308,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
|
|||||||
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
|
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
|
||||||
if return_cost > *gas || data.len() > self.schedule.create_data_limit {
|
if return_cost > *gas || data.len() > self.schedule.create_data_limit {
|
||||||
return match self.schedule.exceptional_failed_code_deposit {
|
return match self.schedule.exceptional_failed_code_deposit {
|
||||||
true => Err(evm::Error::OutOfGas),
|
true => Err(vm::Error::OutOfGas),
|
||||||
false => Ok(*gas)
|
false => Ok(*gas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,11 +321,11 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> evm::Result<()> {
|
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> vm::Result<()> {
|
||||||
use log_entry::LogEntry;
|
use log_entry::LogEntry;
|
||||||
|
|
||||||
if self.static_flag {
|
if self.static_flag {
|
||||||
return Err(evm::Error::MutableCallInStaticContext);
|
return Err(vm::Error::MutableCallInStaticContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
let address = self.origin_info.address.clone();
|
let address = self.origin_info.address.clone();
|
||||||
@ -337,9 +338,9 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> {
|
fn suicide(&mut self, refund_address: &Address) -> vm::Result<()> {
|
||||||
if self.static_flag {
|
if self.static_flag {
|
||||||
return Err(evm::Error::MutableCallInStaticContext);
|
return Err(vm::Error::MutableCallInStaticContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
let address = self.origin_info.address.clone();
|
let address = self.origin_info.address.clone();
|
||||||
@ -396,13 +397,11 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
|
|||||||
mod tests {
|
mod tests {
|
||||||
use util::*;
|
use util::*;
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
use evm::env_info::EnvInfo;
|
use evm::{EnvInfo, Ext, CallType};
|
||||||
use evm::Ext;
|
|
||||||
use state::{State, Substate};
|
use state::{State, Substate};
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
use trace::{NoopTracer, NoopVMTracer};
|
use trace::{NoopTracer, NoopVMTracer};
|
||||||
use evm::CallType;
|
|
||||||
|
|
||||||
fn get_test_origin() -> OriginInfo {
|
fn get_test_origin() -> OriginInfo {
|
||||||
OriginInfo {
|
OriginInfo {
|
||||||
|
@ -15,15 +15,16 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use super::test_common::*;
|
use super::test_common::*;
|
||||||
use evm::action_params::ActionParams;
|
|
||||||
use state::{Backend as StateBackend, State, Substate};
|
use state::{Backend as StateBackend, State, Substate};
|
||||||
use executive::*;
|
use executive::*;
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
use evm::env_info::EnvInfo;
|
use evm::{VMType, Finalize};
|
||||||
use evm;
|
use vm::{
|
||||||
use evm::{Schedule, Ext, Finalize, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData};
|
self, ActionParams, CallType, Schedule, Ext,
|
||||||
|
ContractCreateResult, EnvInfo, MessageCallResult,
|
||||||
|
CreateContractAddress, ReturnData,
|
||||||
|
};
|
||||||
use externalities::*;
|
use externalities::*;
|
||||||
use evm::CallType;
|
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use ethjson;
|
use ethjson;
|
||||||
use trace::{Tracer, NoopTracer};
|
use trace::{Tracer, NoopTracer};
|
||||||
@ -88,27 +89,27 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> TestExt<'a, T, V, B, E>
|
|||||||
impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E>
|
impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E>
|
||||||
where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized
|
where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized
|
||||||
{
|
{
|
||||||
fn storage_at(&self, key: &H256) -> evm::Result<H256> {
|
fn storage_at(&self, key: &H256) -> vm::Result<H256> {
|
||||||
self.ext.storage_at(key)
|
self.ext.storage_at(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> {
|
fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> {
|
||||||
self.ext.set_storage(key, value)
|
self.ext.set_storage(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exists(&self, address: &Address) -> evm::Result<bool> {
|
fn exists(&self, address: &Address) -> vm::Result<bool> {
|
||||||
self.ext.exists(address)
|
self.ext.exists(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exists_and_not_null(&self, address: &Address) -> evm::Result<bool> {
|
fn exists_and_not_null(&self, address: &Address) -> vm::Result<bool> {
|
||||||
self.ext.exists_and_not_null(address)
|
self.ext.exists_and_not_null(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn balance(&self, address: &Address) -> evm::Result<U256> {
|
fn balance(&self, address: &Address) -> vm::Result<U256> {
|
||||||
self.ext.balance(address)
|
self.ext.balance(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn origin_balance(&self) -> evm::Result<U256> {
|
fn origin_balance(&self) -> vm::Result<U256> {
|
||||||
self.ext.origin_balance()
|
self.ext.origin_balance()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,23 +147,23 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E>
|
|||||||
MessageCallResult::Success(*gas, ReturnData::empty())
|
MessageCallResult::Success(*gas, ReturnData::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcode(&self, address: &Address) -> evm::Result<Arc<Bytes>> {
|
fn extcode(&self, address: &Address) -> vm::Result<Arc<Bytes>> {
|
||||||
self.ext.extcode(address)
|
self.ext.extcode(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcodesize(&self, address: &Address) -> evm::Result<usize> {
|
fn extcodesize(&self, address: &Address) -> vm::Result<usize> {
|
||||||
self.ext.extcodesize(address)
|
self.ext.extcodesize(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> evm::Result<()> {
|
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> vm::Result<()> {
|
||||||
self.ext.log(topics, data)
|
self.ext.log(topics, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret(self, gas: &U256, data: &ReturnData) -> Result<U256, evm::Error> {
|
fn ret(self, gas: &U256, data: &ReturnData) -> Result<U256, vm::Error> {
|
||||||
self.ext.ret(gas, data)
|
self.ext.ret(gas, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> {
|
fn suicide(&mut self, refund_address: &Address) -> vm::Result<()> {
|
||||||
self.ext.suicide(refund_address)
|
self.ext.suicide(refund_address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ use spec::Spec;
|
|||||||
use ethjson;
|
use ethjson;
|
||||||
use ethjson::state::test::ForkSpec;
|
use ethjson::state::test::ForkSpec;
|
||||||
use transaction::SignedTransaction;
|
use transaction::SignedTransaction;
|
||||||
use evm::env_info::EnvInfo;
|
use vm::EnvInfo;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref FRONTIER: Spec = ethereum::new_frontier_test();
|
pub static ref FRONTIER: Spec = ethereum::new_frontier_test();
|
||||||
|
@ -106,6 +106,8 @@ extern crate semver;
|
|||||||
extern crate stats;
|
extern crate stats;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate transient_hashmap;
|
extern crate transient_hashmap;
|
||||||
|
extern crate vm;
|
||||||
|
extern crate wasm;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
@ -1112,6 +1112,8 @@ impl MinerService for Miner {
|
|||||||
/// Prepare the block and work if the Engine does not seal internally.
|
/// Prepare the block and work if the Engine does not seal internally.
|
||||||
fn update_sealing(&self, chain: &MiningBlockChainClient) {
|
fn update_sealing(&self, chain: &MiningBlockChainClient) {
|
||||||
trace!(target: "miner", "update_sealing");
|
trace!(target: "miner", "update_sealing");
|
||||||
|
const NO_NEW_CHAIN_WITH_FORKS: &str = "Your chain specification contains one or more hard forks which are required to be \
|
||||||
|
on by default. Please remove these forks and start your chain again.";
|
||||||
|
|
||||||
if self.requires_reseal(chain.chain_info().best_block_number) {
|
if self.requires_reseal(chain.chain_info().best_block_number) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@ -1120,6 +1122,14 @@ impl MinerService for Miner {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
trace!(target: "miner", "update_sealing: preparing a block");
|
trace!(target: "miner", "update_sealing: preparing a block");
|
||||||
let (block, original_work_hash) = self.prepare_block(chain);
|
let (block, original_work_hash) = self.prepare_block(chain);
|
||||||
|
|
||||||
|
// refuse to seal the first block of the chain if it contains hard forks
|
||||||
|
// which should be on by default.
|
||||||
|
if block.block().fields().header.number() == 1 && self.engine.params().contains_bugfix_hard_fork() {
|
||||||
|
warn!("{}", NO_NEW_CHAIN_WITH_FORKS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
match self.engine.seals_internally() {
|
match self.engine.seals_internally() {
|
||||||
Some(true) => {
|
Some(true) => {
|
||||||
trace!(target: "miner", "update_sealing: engine indicates internal sealing");
|
trace!(target: "miner", "update_sealing: engine indicates internal sealing");
|
||||||
@ -1127,11 +1137,11 @@ impl MinerService for Miner {
|
|||||||
trace!(target: "miner", "update_sealing: imported internally sealed block");
|
trace!(target: "miner", "update_sealing: imported internally sealed block");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Some(false) => trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now"),
|
||||||
None => {
|
None => {
|
||||||
trace!(target: "miner", "update_sealing: engine does not seal internally, preparing work");
|
trace!(target: "miner", "update_sealing: engine does not seal internally, preparing work");
|
||||||
self.prepare_work(block, original_work_hash)
|
self.prepare_work(block, original_work_hash)
|
||||||
},
|
},
|
||||||
_ => trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
"engine": {
|
"engine": {
|
||||||
"authorityRound": {
|
"authorityRound": {
|
||||||
"params": {
|
"params": {
|
||||||
"gasLimitBoundDivisor": "0x0400",
|
|
||||||
"stepDuration": 1,
|
"stepDuration": 1,
|
||||||
"startStep": 0,
|
"startStep": 0,
|
||||||
"validators": {
|
"validators": {
|
||||||
@ -17,6 +16,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
"accountStartNonce": "0x0",
|
"accountStartNonce": "0x0",
|
||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
|
@ -20,10 +20,9 @@ use rustc_hex::FromHex;
|
|||||||
use super::genesis::Genesis;
|
use super::genesis::Genesis;
|
||||||
use super::seal::Generic as GenericSeal;
|
use super::seal::Generic as GenericSeal;
|
||||||
|
|
||||||
use evm::action_params::{ActionValue, ActionParams};
|
|
||||||
use builtin::Builtin;
|
use builtin::Builtin;
|
||||||
use engines::{Engine, NullEngine, InstantSeal, BasicAuthority, AuthorityRound, Tendermint, DEFAULT_BLOCKHASH_CONTRACT};
|
use engines::{Engine, NullEngine, InstantSeal, BasicAuthority, AuthorityRound, Tendermint, DEFAULT_BLOCKHASH_CONTRACT};
|
||||||
use evm::env_info::EnvInfo;
|
use vm::{EnvInfo, CallType, ActionValue, ActionParams};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use ethereum;
|
use ethereum;
|
||||||
use ethjson;
|
use ethjson;
|
||||||
@ -36,10 +35,14 @@ use state_db::StateDB;
|
|||||||
use state::{Backend, State, Substate};
|
use state::{Backend, State, Substate};
|
||||||
use state::backend::Basic as BasicBackend;
|
use state::backend::Basic as BasicBackend;
|
||||||
use trace::{NoopTracer, NoopVMTracer};
|
use trace::{NoopTracer, NoopVMTracer};
|
||||||
use evm::CallType;
|
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
/// Parameters common to all engines.
|
/// Parameters common to ethereum-like blockchains.
|
||||||
|
/// NOTE: when adding bugfix hard-fork parameters,
|
||||||
|
/// add to `contains_bugfix_hard_fork`
|
||||||
|
///
|
||||||
|
/// we define a "bugfix" hard fork as any hard fork which
|
||||||
|
/// you would put on-by-default in a new chain.
|
||||||
#[derive(Debug, PartialEq, Default)]
|
#[derive(Debug, PartialEq, Default)]
|
||||||
#[cfg_attr(test, derive(Clone))]
|
#[cfg_attr(test, derive(Clone))]
|
||||||
pub struct CommonParams {
|
pub struct CommonParams {
|
||||||
@ -59,8 +62,10 @@ pub struct CommonParams {
|
|||||||
pub fork_block: Option<(BlockNumber, H256)>,
|
pub fork_block: Option<(BlockNumber, H256)>,
|
||||||
/// Number of first block where EIP-98 rules begin.
|
/// Number of first block where EIP-98 rules begin.
|
||||||
pub eip98_transition: BlockNumber,
|
pub eip98_transition: BlockNumber,
|
||||||
|
/// Number of first block where EIP-155 rules begin.
|
||||||
|
pub eip155_transition: BlockNumber,
|
||||||
/// Validate block receipts root.
|
/// Validate block receipts root.
|
||||||
pub validate_receipts_transition: u64,
|
pub validate_receipts_transition: BlockNumber,
|
||||||
/// Number of first block where EIP-86 (Metropolis) rules begin.
|
/// Number of first block where EIP-86 (Metropolis) rules begin.
|
||||||
pub eip86_transition: BlockNumber,
|
pub eip86_transition: BlockNumber,
|
||||||
/// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin.
|
/// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin.
|
||||||
@ -85,18 +90,24 @@ pub struct CommonParams {
|
|||||||
pub remove_dust_contracts: bool,
|
pub remove_dust_contracts: bool,
|
||||||
/// Wasm support
|
/// Wasm support
|
||||||
pub wasm: bool,
|
pub wasm: bool,
|
||||||
|
/// Gas limit bound divisor (how much gas limit can change per block)
|
||||||
|
pub gas_limit_bound_divisor: U256,
|
||||||
|
/// Block reward in wei.
|
||||||
|
pub block_reward: U256,
|
||||||
|
/// Registrar contract address.
|
||||||
|
pub registrar: Address,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommonParams {
|
impl CommonParams {
|
||||||
/// Schedule for an EVM in the post-EIP-150-era of the Ethereum main net.
|
/// Schedule for an EVM in the post-EIP-150-era of the Ethereum main net.
|
||||||
pub fn schedule(&self, block_number: u64) -> ::evm::Schedule {
|
pub fn schedule(&self, block_number: u64) -> ::vm::Schedule {
|
||||||
let mut schedule = ::evm::Schedule::new_post_eip150(usize::max_value(), true, true, true);
|
let mut schedule = ::vm::Schedule::new_post_eip150(usize::max_value(), true, true, true);
|
||||||
self.update_schedule(block_number, &mut schedule);
|
self.update_schedule(block_number, &mut schedule);
|
||||||
schedule
|
schedule
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply common spec config parameters to the schedule.
|
/// Apply common spec config parameters to the schedule.
|
||||||
pub fn update_schedule(&self, block_number: u64, schedule: &mut ::evm::Schedule) {
|
pub fn update_schedule(&self, block_number: u64, schedule: &mut ::vm::Schedule) {
|
||||||
schedule.have_create2 = block_number >= self.eip86_transition;
|
schedule.have_create2 = block_number >= self.eip86_transition;
|
||||||
schedule.have_revert = block_number >= self.eip140_transition;
|
schedule.have_revert = block_number >= self.eip140_transition;
|
||||||
schedule.have_static_call = block_number >= self.eip214_transition;
|
schedule.have_static_call = block_number >= self.eip214_transition;
|
||||||
@ -106,11 +117,24 @@ impl CommonParams {
|
|||||||
}
|
}
|
||||||
if block_number >= self.dust_protection_transition {
|
if block_number >= self.dust_protection_transition {
|
||||||
schedule.kill_dust = match self.remove_dust_contracts {
|
schedule.kill_dust = match self.remove_dust_contracts {
|
||||||
true => ::evm::CleanDustMode::WithCodeAndStorage,
|
true => ::vm::CleanDustMode::WithCodeAndStorage,
|
||||||
false => ::evm::CleanDustMode::BasicOnly,
|
false => ::vm::CleanDustMode::BasicOnly,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether these params contain any bug-fix hard forks.
|
||||||
|
pub fn contains_bugfix_hard_fork(&self) -> bool {
|
||||||
|
self.eip98_transition != 0 &&
|
||||||
|
self.eip155_transition != 0 &&
|
||||||
|
self.validate_receipts_transition != 0 &&
|
||||||
|
self.eip86_transition != 0 &&
|
||||||
|
self.eip140_transition != 0 &&
|
||||||
|
self.eip210_transition != 0 &&
|
||||||
|
self.eip211_transition != 0 &&
|
||||||
|
self.eip214_transition != 0 &&
|
||||||
|
self.dust_protection_transition != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ethjson::spec::Params> for CommonParams {
|
impl From<ethjson::spec::Params> for CommonParams {
|
||||||
@ -124,6 +148,7 @@ impl From<ethjson::spec::Params> for CommonParams {
|
|||||||
min_gas_limit: p.min_gas_limit.into(),
|
min_gas_limit: p.min_gas_limit.into(),
|
||||||
fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
|
fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
|
||||||
eip98_transition: p.eip98_transition.map_or(0, Into::into),
|
eip98_transition: p.eip98_transition.map_or(0, Into::into),
|
||||||
|
eip155_transition: p.eip155_transition.map_or(0, Into::into),
|
||||||
validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
|
validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
|
||||||
eip86_transition: p.eip86_transition.map_or(BlockNumber::max_value(), Into::into),
|
eip86_transition: p.eip86_transition.map_or(BlockNumber::max_value(), Into::into),
|
||||||
eip140_transition: p.eip140_transition.map_or(BlockNumber::max_value(), Into::into),
|
eip140_transition: p.eip140_transition.map_or(BlockNumber::max_value(), Into::into),
|
||||||
@ -139,6 +164,9 @@ impl From<ethjson::spec::Params> for CommonParams {
|
|||||||
nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into),
|
nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into),
|
||||||
remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false),
|
remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false),
|
||||||
wasm: p.wasm.unwrap_or(false),
|
wasm: p.wasm.unwrap_or(false),
|
||||||
|
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
|
||||||
|
block_reward: p.block_reward.map_or_else(U256::zero, Into::into),
|
||||||
|
registrar: p.registrar.map_or_else(Address::new, Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,7 +270,7 @@ impl Spec {
|
|||||||
) -> Arc<Engine> {
|
) -> Arc<Engine> {
|
||||||
match engine_spec {
|
match engine_spec {
|
||||||
ethjson::spec::Engine::Null => Arc::new(NullEngine::new(params, builtins)),
|
ethjson::spec::Engine::Null => Arc::new(NullEngine::new(params, builtins)),
|
||||||
ethjson::spec::Engine::InstantSeal(instant) => Arc::new(InstantSeal::new(params, instant.params.registrar.map_or_else(Address::new, Into::into), builtins)),
|
ethjson::spec::Engine::InstantSeal => Arc::new(InstantSeal::new(params, builtins)),
|
||||||
ethjson::spec::Engine::Ethash(ethash) => Arc::new(ethereum::Ethash::new(cache_dir, params, From::from(ethash.params), builtins)),
|
ethjson::spec::Engine::Ethash(ethash) => Arc::new(ethereum::Ethash::new(cache_dir, params, From::from(ethash.params), builtins)),
|
||||||
ethjson::spec::Engine::BasicAuthority(basic_authority) => Arc::new(BasicAuthority::new(params, From::from(basic_authority.params), builtins)),
|
ethjson::spec::Engine::BasicAuthority(basic_authority) => Arc::new(BasicAuthority::new(params, From::from(basic_authority.params), builtins)),
|
||||||
ethjson::spec::Engine::AuthorityRound(authority_round) => AuthorityRound::new(params, From::from(authority_round.params), builtins).expect("Failed to start AuthorityRound consensus engine."),
|
ethjson::spec::Engine::AuthorityRound(authority_round) => AuthorityRound::new(params, From::from(authority_round.params), builtins).expect("Failed to start AuthorityRound consensus engine."),
|
||||||
|
@ -24,7 +24,7 @@ use std::collections::hash_map::Entry;
|
|||||||
|
|
||||||
use receipt::Receipt;
|
use receipt::Receipt;
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
use evm::env_info::EnvInfo;
|
use vm::EnvInfo;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use executive::{Executive, TransactOptions};
|
use executive::{Executive, TransactOptions};
|
||||||
use factory::Factories;
|
use factory::Factories;
|
||||||
@ -982,7 +982,7 @@ mod tests {
|
|||||||
use ethkey::Secret;
|
use ethkey::Secret;
|
||||||
use util::{U256, H256, Address, Hashable};
|
use util::{U256, H256, Address, Hashable};
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use evm::env_info::EnvInfo;
|
use vm::EnvInfo;
|
||||||
use spec::*;
|
use spec::*;
|
||||||
use transaction::*;
|
use transaction::*;
|
||||||
use ethcore_logger::init_log;
|
use ethcore_logger::init_log;
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
//! Tests of EVM integration with transaction execution.
|
//! Tests of EVM integration with transaction execution.
|
||||||
|
|
||||||
use evm::action_params::{ActionParams, ActionValue};
|
use vm::{EnvInfo, ActionParams, ActionValue, CallType};
|
||||||
use evm::env_info::EnvInfo;
|
|
||||||
use evm::{Factory, VMType};
|
use evm::{Factory, VMType};
|
||||||
use evm::call_type::CallType;
|
|
||||||
use executive::Executive;
|
use executive::Executive;
|
||||||
use state::Substate;
|
use state::Substate;
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
|
@ -396,14 +396,11 @@ pub fn get_bad_state_dummy_block() -> Bytes {
|
|||||||
|
|
||||||
pub fn get_default_ethash_params() -> EthashParams {
|
pub fn get_default_ethash_params() -> EthashParams {
|
||||||
EthashParams {
|
EthashParams {
|
||||||
gas_limit_bound_divisor: U256::from(1024),
|
|
||||||
minimum_difficulty: U256::from(131072),
|
minimum_difficulty: U256::from(131072),
|
||||||
difficulty_bound_divisor: U256::from(2048),
|
difficulty_bound_divisor: U256::from(2048),
|
||||||
difficulty_increment_divisor: 10,
|
difficulty_increment_divisor: 10,
|
||||||
metropolis_difficulty_increment_divisor: 9,
|
metropolis_difficulty_increment_divisor: 9,
|
||||||
duration_limit: 13,
|
duration_limit: 13,
|
||||||
block_reward: U256::from(0),
|
|
||||||
registrar: "0000000000000000000000000000000000000001".into(),
|
|
||||||
homestead_transition: 1150000,
|
homestead_transition: 1150000,
|
||||||
dao_hardfork_transition: u64::max_value(),
|
dao_hardfork_transition: u64::max_value(),
|
||||||
dao_hardfork_beneficiary: "0000000000000000000000000000000000000001".into(),
|
dao_hardfork_beneficiary: "0000000000000000000000000000000000000001".into(),
|
||||||
@ -413,7 +410,6 @@ pub fn get_default_ethash_params() -> EthashParams{
|
|||||||
bomb_defuse_transition: u64::max_value(),
|
bomb_defuse_transition: u64::max_value(),
|
||||||
eip100b_transition: u64::max_value(),
|
eip100b_transition: u64::max_value(),
|
||||||
eip150_transition: u64::max_value(),
|
eip150_transition: u64::max_value(),
|
||||||
eip155_transition: u64::max_value(),
|
|
||||||
eip160_transition: u64::max_value(),
|
eip160_transition: u64::max_value(),
|
||||||
eip161abc_transition: u64::max_value(),
|
eip161abc_transition: u64::max_value(),
|
||||||
eip161d_transition: u64::max_value(),
|
eip161d_transition: u64::max_value(),
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! Simple executive tracer.
|
//! Simple executive tracer.
|
||||||
|
|
||||||
use util::{Bytes, Address, U256};
|
use util::{Bytes, Address, U256};
|
||||||
use evm::action_params::ActionParams;
|
use vm::ActionParams;
|
||||||
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide};
|
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide};
|
||||||
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
|
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ pub use self::types::filter::{Filter, AddressesFilter};
|
|||||||
|
|
||||||
use util::{Bytes, Address, U256, H256, DBTransaction};
|
use util::{Bytes, Address, U256, H256, DBTransaction};
|
||||||
use self::trace::{Call, Create};
|
use self::trace::{Call, Create};
|
||||||
use evm::action_params::ActionParams;
|
use vm::ActionParams;
|
||||||
use header::BlockNumber;
|
use header::BlockNumber;
|
||||||
|
|
||||||
/// This trait is used by executive to build traces.
|
/// This trait is used by executive to build traces.
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! Nonoperative tracer.
|
//! Nonoperative tracer.
|
||||||
|
|
||||||
use util::{Bytes, Address, U256};
|
use util::{Bytes, Address, U256};
|
||||||
use evm::action_params::ActionParams;
|
use vm::ActionParams;
|
||||||
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
|
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
|
||||||
use trace::trace::{Call, Create, VMTrace};
|
use trace::trace::{Call, Create, VMTrace};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use rlp::{Encodable, RlpStream, Decodable, DecoderError, UntrustedRlp};
|
use rlp::{Encodable, RlpStream, Decodable, DecoderError, UntrustedRlp};
|
||||||
use evm::Error as EvmError;
|
use vm::Error as VmError;
|
||||||
|
|
||||||
/// Trace evm errors.
|
/// Trace evm errors.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -45,24 +45,24 @@ pub enum Error {
|
|||||||
Wasm,
|
Wasm,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a EvmError> for Error {
|
impl<'a> From<&'a VmError> for Error {
|
||||||
fn from(e: &'a EvmError) -> Self {
|
fn from(e: &'a VmError) -> Self {
|
||||||
match *e {
|
match *e {
|
||||||
EvmError::OutOfGas => Error::OutOfGas,
|
VmError::OutOfGas => Error::OutOfGas,
|
||||||
EvmError::BadJumpDestination { .. } => Error::BadJumpDestination,
|
VmError::BadJumpDestination { .. } => Error::BadJumpDestination,
|
||||||
EvmError::BadInstruction { .. } => Error::BadInstruction,
|
VmError::BadInstruction { .. } => Error::BadInstruction,
|
||||||
EvmError::StackUnderflow { .. } => Error::StackUnderflow,
|
VmError::StackUnderflow { .. } => Error::StackUnderflow,
|
||||||
EvmError::OutOfStack { .. } => Error::OutOfStack,
|
VmError::OutOfStack { .. } => Error::OutOfStack,
|
||||||
EvmError::BuiltIn { .. } => Error::BuiltIn,
|
VmError::BuiltIn { .. } => Error::BuiltIn,
|
||||||
EvmError::Wasm { .. } => Error::Wasm,
|
VmError::Wasm { .. } => Error::Wasm,
|
||||||
EvmError::Internal(_) => Error::Internal,
|
VmError::Internal(_) => Error::Internal,
|
||||||
EvmError::MutableCallInStaticContext => Error::MutableCallInStaticContext,
|
VmError::MutableCallInStaticContext => Error::MutableCallInStaticContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<EvmError> for Error {
|
impl From<VmError> for Error {
|
||||||
fn from(e: EvmError) -> Self {
|
fn from(e: VmError) -> Self {
|
||||||
Error::from(&e)
|
Error::from(&e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ use util::sha3::Hashable;
|
|||||||
use util::bloom::Bloomable;
|
use util::bloom::Bloomable;
|
||||||
use rlp::*;
|
use rlp::*;
|
||||||
|
|
||||||
use evm::action_params::ActionParams;
|
use vm::ActionParams;
|
||||||
use basic_types::LogBloom;
|
use basic_types::LogBloom;
|
||||||
use evm::CallType;
|
use evm::CallType;
|
||||||
use super::error::Error;
|
use super::error::Error;
|
||||||
|
14
ethcore/vm/Cargo.toml
Normal file
14
ethcore/vm/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "vm"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
byteorder = "1.0"
|
||||||
|
ethcore-util = { path = "../../util" }
|
||||||
|
log = "0.3"
|
||||||
|
common-types = { path = "../types" }
|
||||||
|
evmjit = { path = "../../evmjit", optional = true }
|
||||||
|
ethjson = { path = "../../json" }
|
||||||
|
lazy_static = "0.2"
|
||||||
|
rlp = { path = "../../util/rlp" }
|
@ -20,7 +20,7 @@ use util::hash::{H256};
|
|||||||
use util::sha3::{Hashable, SHA3_EMPTY};
|
use util::sha3::{Hashable, SHA3_EMPTY};
|
||||||
use ethjson;
|
use ethjson;
|
||||||
|
|
||||||
use {CallType};
|
use call_type::CallType;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
100
ethcore/vm/src/error.rs
Normal file
100
ethcore/vm/src/error.rs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity 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.
|
||||||
|
|
||||||
|
// Parity 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 Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! VM errors module
|
||||||
|
|
||||||
|
use util::trie;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// VM errors.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Error {
|
||||||
|
/// `OutOfGas` is returned when transaction execution runs out of gas.
|
||||||
|
/// The state should be reverted to the state from before the
|
||||||
|
/// transaction execution. But it does not mean that transaction
|
||||||
|
/// was invalid. Balance still should be transfered and nonce
|
||||||
|
/// should be increased.
|
||||||
|
OutOfGas,
|
||||||
|
/// `BadJumpDestination` is returned when execution tried to move
|
||||||
|
/// to position that wasn't marked with JUMPDEST instruction
|
||||||
|
BadJumpDestination {
|
||||||
|
/// Position the code tried to jump to.
|
||||||
|
destination: usize
|
||||||
|
},
|
||||||
|
/// `BadInstructions` is returned when given instruction is not supported
|
||||||
|
BadInstruction {
|
||||||
|
/// Unrecognized opcode
|
||||||
|
instruction: u8,
|
||||||
|
},
|
||||||
|
/// `StackUnderflow` when there is not enough stack elements to execute instruction
|
||||||
|
StackUnderflow {
|
||||||
|
/// Invoked instruction
|
||||||
|
instruction: &'static str,
|
||||||
|
/// How many stack elements was requested by instruction
|
||||||
|
wanted: usize,
|
||||||
|
/// How many elements were on stack
|
||||||
|
on_stack: usize
|
||||||
|
},
|
||||||
|
/// When execution would exceed defined Stack Limit
|
||||||
|
OutOfStack {
|
||||||
|
/// Invoked instruction
|
||||||
|
instruction: &'static str,
|
||||||
|
/// How many stack elements instruction wanted to push
|
||||||
|
wanted: usize,
|
||||||
|
/// What was the stack limit
|
||||||
|
limit: usize
|
||||||
|
},
|
||||||
|
/// Built-in contract failed on given input
|
||||||
|
BuiltIn(&'static str),
|
||||||
|
/// When execution tries to modify the state in static context
|
||||||
|
MutableCallInStaticContext,
|
||||||
|
/// Likely to cause consensus issues.
|
||||||
|
Internal(String),
|
||||||
|
/// Wasm runtime error
|
||||||
|
Wasm(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl From<Box<trie::TrieError>> for Error {
|
||||||
|
fn from(err: Box<trie::TrieError>) -> Self {
|
||||||
|
Error::Internal(format!("Internal error: {}", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl From<wasm::RuntimeError> for Error {
|
||||||
|
// fn from(err: wasm::RuntimeError) -> Self {
|
||||||
|
// Error::Wasm(format!("Runtime error: {:?}", err))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use self::Error::*;
|
||||||
|
match *self {
|
||||||
|
OutOfGas => write!(f, "Out of gas"),
|
||||||
|
BadJumpDestination { destination } => write!(f, "Bad jump destination {:x}", destination),
|
||||||
|
BadInstruction { instruction } => write!(f, "Bad instruction {:x}", instruction),
|
||||||
|
StackUnderflow { instruction, wanted, on_stack } => write!(f, "Stack underflow {} {}/{}", instruction, wanted, on_stack),
|
||||||
|
OutOfStack { instruction, wanted, limit } => write!(f, "Out of stack {} {}/{}", instruction, wanted, limit),
|
||||||
|
BuiltIn(name) => write!(f, "Built-in failed: {}", name),
|
||||||
|
Internal(ref msg) => write!(f, "Internal error: {}", msg),
|
||||||
|
MutableCallInStaticContext => write!(f, "Mutable call in static context"),
|
||||||
|
Wasm(ref msg) => write!(f, "Internal error: {}", msg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result<T> = ::std::result::Result<T, Error>;
|
@ -20,7 +20,8 @@ use util::*;
|
|||||||
use call_type::CallType;
|
use call_type::CallType;
|
||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
use schedule::Schedule;
|
use schedule::Schedule;
|
||||||
use evm::{self, ReturnData};
|
use return_data::ReturnData;
|
||||||
|
use error::Result;
|
||||||
|
|
||||||
/// Result of externalities create function.
|
/// Result of externalities create function.
|
||||||
pub enum ContractCreateResult {
|
pub enum ContractCreateResult {
|
||||||
@ -56,22 +57,22 @@ pub enum CreateContractAddress {
|
|||||||
/// Externalities interface for EVMs
|
/// Externalities interface for EVMs
|
||||||
pub trait Ext {
|
pub trait Ext {
|
||||||
/// Returns a value for given key.
|
/// Returns a value for given key.
|
||||||
fn storage_at(&self, key: &H256) -> evm::Result<H256>;
|
fn storage_at(&self, key: &H256) -> Result<H256>;
|
||||||
|
|
||||||
/// Stores a value for given key.
|
/// Stores a value for given key.
|
||||||
fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()>;
|
fn set_storage(&mut self, key: H256, value: H256) -> Result<()>;
|
||||||
|
|
||||||
/// Determine whether an account exists.
|
/// Determine whether an account exists.
|
||||||
fn exists(&self, address: &Address) -> evm::Result<bool>;
|
fn exists(&self, address: &Address) -> Result<bool>;
|
||||||
|
|
||||||
/// Determine whether an account exists and is not null (zero balance/nonce, no code).
|
/// Determine whether an account exists and is not null (zero balance/nonce, no code).
|
||||||
fn exists_and_not_null(&self, address: &Address) -> evm::Result<bool>;
|
fn exists_and_not_null(&self, address: &Address) -> Result<bool>;
|
||||||
|
|
||||||
/// Balance of the origin account.
|
/// Balance of the origin account.
|
||||||
fn origin_balance(&self) -> evm::Result<U256>;
|
fn origin_balance(&self) -> Result<U256>;
|
||||||
|
|
||||||
/// Returns address balance.
|
/// Returns address balance.
|
||||||
fn balance(&self, address: &Address) -> evm::Result<U256>;
|
fn balance(&self, address: &Address) -> Result<U256>;
|
||||||
|
|
||||||
/// Returns the hash of one of the 256 most recent complete blocks.
|
/// Returns the hash of one of the 256 most recent complete blocks.
|
||||||
fn blockhash(&mut self, number: &U256) -> H256;
|
fn blockhash(&mut self, number: &U256) -> H256;
|
||||||
@ -99,21 +100,21 @@ pub trait Ext {
|
|||||||
) -> MessageCallResult;
|
) -> MessageCallResult;
|
||||||
|
|
||||||
/// Returns code at given address
|
/// Returns code at given address
|
||||||
fn extcode(&self, address: &Address) -> evm::Result<Arc<Bytes>>;
|
fn extcode(&self, address: &Address) -> Result<Arc<Bytes>>;
|
||||||
|
|
||||||
/// Returns code size at given address
|
/// Returns code size at given address
|
||||||
fn extcodesize(&self, address: &Address) -> evm::Result<usize>;
|
fn extcodesize(&self, address: &Address) -> Result<usize>;
|
||||||
|
|
||||||
/// Creates log entry with given topics and data
|
/// Creates log entry with given topics and data
|
||||||
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> evm::Result<()>;
|
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> Result<()>;
|
||||||
|
|
||||||
/// Should be called when transaction calls `RETURN` opcode.
|
/// Should be called when transaction calls `RETURN` opcode.
|
||||||
/// Returns gas_left if cost of returning the data is not too high.
|
/// Returns gas_left if cost of returning the data is not too high.
|
||||||
fn ret(self, gas: &U256, data: &ReturnData) -> evm::Result<U256>;
|
fn ret(self, gas: &U256, data: &ReturnData) -> Result<U256>;
|
||||||
|
|
||||||
/// Should be called when contract commits suicide.
|
/// Should be called when contract commits suicide.
|
||||||
/// Address to which funds should be refunded.
|
/// Address to which funds should be refunded.
|
||||||
fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> ;
|
fn suicide(&mut self, refund_address: &Address) -> Result<()> ;
|
||||||
|
|
||||||
/// Returns schedule.
|
/// Returns schedule.
|
||||||
fn schedule(&self) -> &Schedule;
|
fn schedule(&self) -> &Schedule;
|
48
ethcore/vm/src/lib.rs
Normal file
48
ethcore/vm/src/lib.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity 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.
|
||||||
|
|
||||||
|
// Parity 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 Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Virtual machines support library
|
||||||
|
|
||||||
|
extern crate ethcore_util as util;
|
||||||
|
extern crate common_types as types;
|
||||||
|
extern crate ethjson;
|
||||||
|
extern crate rlp;
|
||||||
|
|
||||||
|
mod action_params;
|
||||||
|
mod call_type;
|
||||||
|
mod env_info;
|
||||||
|
mod schedule;
|
||||||
|
mod ext;
|
||||||
|
mod return_data;
|
||||||
|
mod error;
|
||||||
|
|
||||||
|
pub mod tests;
|
||||||
|
|
||||||
|
pub use action_params::{ActionParams, ActionValue};
|
||||||
|
pub use call_type::CallType;
|
||||||
|
pub use env_info::{EnvInfo, LastHashes};
|
||||||
|
pub use schedule::{Schedule, CleanDustMode};
|
||||||
|
pub use ext::{Ext, MessageCallResult, ContractCreateResult, CreateContractAddress};
|
||||||
|
pub use return_data::{ReturnData, GasLeft};
|
||||||
|
pub use error::{Error, Result};
|
||||||
|
|
||||||
|
/// Virtual Machine interface
|
||||||
|
pub trait Vm {
|
||||||
|
/// This function should be used to execute transaction.
|
||||||
|
/// It returns either an error, a known amount of gas left, or parameters to be used
|
||||||
|
/// to compute the final gas left.
|
||||||
|
fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result<GasLeft>;
|
||||||
|
}
|
68
ethcore/vm/src/return_data.rs
Normal file
68
ethcore/vm/src/return_data.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
// Parity 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.
|
||||||
|
|
||||||
|
// Parity 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 Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Return data structures
|
||||||
|
|
||||||
|
use util::U256;
|
||||||
|
|
||||||
|
/// Return data buffer. Holds memory from a previous call and a slice into that memory.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ReturnData {
|
||||||
|
mem: Vec<u8>,
|
||||||
|
offset: usize,
|
||||||
|
size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::ops::Deref for ReturnData {
|
||||||
|
type Target = [u8];
|
||||||
|
fn deref(&self) -> &[u8] {
|
||||||
|
&self.mem[self.offset..self.offset + self.size]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReturnData {
|
||||||
|
/// Create empty `ReturnData`.
|
||||||
|
pub fn empty() -> Self {
|
||||||
|
ReturnData {
|
||||||
|
mem: Vec::new(),
|
||||||
|
offset: 0,
|
||||||
|
size: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Create `ReturnData` from give buffer and slice.
|
||||||
|
pub fn new(mem: Vec<u8>, offset: usize, size: usize) -> Self {
|
||||||
|
ReturnData {
|
||||||
|
mem: mem,
|
||||||
|
offset: offset,
|
||||||
|
size: size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gas Left: either it is a known value, or it needs to be computed by processing
|
||||||
|
/// a return instruction.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum GasLeft {
|
||||||
|
/// Known gas left
|
||||||
|
Known(U256),
|
||||||
|
/// Return or Revert instruction must be processed.
|
||||||
|
NeedsReturn {
|
||||||
|
/// Amount of gas left.
|
||||||
|
gas_left: U256,
|
||||||
|
/// Return data buffer.
|
||||||
|
data: ReturnData,
|
||||||
|
/// Apply or revert state changes on revert.
|
||||||
|
apply_state: bool
|
||||||
|
},
|
||||||
|
}
|
@ -250,6 +250,12 @@ impl Schedule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Schedule {
|
||||||
|
fn default() -> Self {
|
||||||
|
Schedule::new_frontier()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn schedule_evm_assumptions() {
|
fn schedule_evm_assumptions() {
|
||||||
@ -260,3 +266,4 @@ fn schedule_evm_assumptions() {
|
|||||||
assert_eq!(s1.quad_coeff_div, 512);
|
assert_eq!(s1.quad_coeff_div, 512);
|
||||||
assert_eq!(s2.quad_coeff_div, 512);
|
assert_eq!(s2.quad_coeff_div, 512);
|
||||||
}
|
}
|
||||||
|
|
187
ethcore/vm/src/tests.rs
Normal file
187
ethcore/vm/src/tests.rs
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity 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.
|
||||||
|
|
||||||
|
// Parity 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 Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use util::{H256, U256, Address, Bytes};
|
||||||
|
use {
|
||||||
|
CallType, Schedule, EnvInfo,
|
||||||
|
ReturnData, Ext, ContractCreateResult, MessageCallResult,
|
||||||
|
CreateContractAddress, Result, GasLeft,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct FakeLogEntry {
|
||||||
|
pub topics: Vec<H256>,
|
||||||
|
pub data: Bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub enum FakeCallType {
|
||||||
|
Call, Create
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct FakeCall {
|
||||||
|
pub call_type: FakeCallType,
|
||||||
|
pub gas: U256,
|
||||||
|
pub sender_address: Option<Address>,
|
||||||
|
pub receive_address: Option<Address>,
|
||||||
|
pub value: Option<U256>,
|
||||||
|
pub data: Bytes,
|
||||||
|
pub code_address: Option<Address>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fake externalities test structure.
|
||||||
|
///
|
||||||
|
/// Can't do recursive calls.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct FakeExt {
|
||||||
|
pub store: HashMap<H256, H256>,
|
||||||
|
pub suicides: HashSet<Address>,
|
||||||
|
pub calls: HashSet<FakeCall>,
|
||||||
|
pub sstore_clears: usize,
|
||||||
|
pub depth: usize,
|
||||||
|
pub blockhashes: HashMap<U256, H256>,
|
||||||
|
pub codes: HashMap<Address, Arc<Bytes>>,
|
||||||
|
pub logs: Vec<FakeLogEntry>,
|
||||||
|
pub info: EnvInfo,
|
||||||
|
pub schedule: Schedule,
|
||||||
|
pub balances: HashMap<Address, U256>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// similar to the normal `finalize` function, but ignoring NeedsReturn.
|
||||||
|
pub fn test_finalize(res: Result<GasLeft>) -> Result<U256> {
|
||||||
|
match res {
|
||||||
|
Ok(GasLeft::Known(gas)) => Ok(gas),
|
||||||
|
Ok(GasLeft::NeedsReturn{..}) => unimplemented!(), // since ret is unimplemented.
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FakeExt {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
FakeExt::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ext for FakeExt {
|
||||||
|
fn storage_at(&self, key: &H256) -> Result<H256> {
|
||||||
|
Ok(self.store.get(key).unwrap_or(&H256::new()).clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_storage(&mut self, key: H256, value: H256) -> Result<()> {
|
||||||
|
self.store.insert(key, value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exists(&self, address: &Address) -> Result<bool> {
|
||||||
|
Ok(self.balances.contains_key(address))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exists_and_not_null(&self, address: &Address) -> Result<bool> {
|
||||||
|
Ok(self.balances.get(address).map_or(false, |b| !b.is_zero()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn origin_balance(&self) -> Result<U256> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn balance(&self, address: &Address) -> Result<U256> {
|
||||||
|
Ok(self.balances[address])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blockhash(&mut self, number: &U256) -> H256 {
|
||||||
|
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
|
||||||
|
self.calls.insert(FakeCall {
|
||||||
|
call_type: FakeCallType::Create,
|
||||||
|
gas: *gas,
|
||||||
|
sender_address: None,
|
||||||
|
receive_address: None,
|
||||||
|
value: Some(*value),
|
||||||
|
data: code.to_vec(),
|
||||||
|
code_address: None
|
||||||
|
});
|
||||||
|
ContractCreateResult::Failed
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self,
|
||||||
|
gas: &U256,
|
||||||
|
sender_address: &Address,
|
||||||
|
receive_address: &Address,
|
||||||
|
value: Option<U256>,
|
||||||
|
data: &[u8],
|
||||||
|
code_address: &Address,
|
||||||
|
_output: &mut [u8],
|
||||||
|
_call_type: CallType
|
||||||
|
) -> MessageCallResult {
|
||||||
|
|
||||||
|
self.calls.insert(FakeCall {
|
||||||
|
call_type: FakeCallType::Call,
|
||||||
|
gas: *gas,
|
||||||
|
sender_address: Some(sender_address.clone()),
|
||||||
|
receive_address: Some(receive_address.clone()),
|
||||||
|
value: value,
|
||||||
|
data: data.to_vec(),
|
||||||
|
code_address: Some(code_address.clone())
|
||||||
|
});
|
||||||
|
MessageCallResult::Success(*gas, ReturnData::empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extcode(&self, address: &Address) -> Result<Arc<Bytes>> {
|
||||||
|
Ok(self.codes.get(address).unwrap_or(&Arc::new(Bytes::new())).clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extcodesize(&self, address: &Address) -> Result<usize> {
|
||||||
|
Ok(self.codes.get(address).map_or(0, |c| c.len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> Result<()> {
|
||||||
|
self.logs.push(FakeLogEntry {
|
||||||
|
topics: topics,
|
||||||
|
data: data.to_vec()
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ret(self, _gas: &U256, _data: &ReturnData) -> Result<U256> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn suicide(&mut self, refund_address: &Address) -> Result<()> {
|
||||||
|
self.suicides.insert(refund_address.clone());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schedule(&self) -> &Schedule {
|
||||||
|
&self.schedule
|
||||||
|
}
|
||||||
|
|
||||||
|
fn env_info(&self) -> &EnvInfo {
|
||||||
|
&self.info
|
||||||
|
}
|
||||||
|
|
||||||
|
fn depth(&self) -> usize {
|
||||||
|
self.depth
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inc_sstore_clears(&mut self) {
|
||||||
|
self.sstore_clears += 1;
|
||||||
|
}
|
||||||
|
}
|
13
ethcore/wasm/Cargo.toml
Normal file
13
ethcore/wasm/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasm"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
byteorder = "1.0"
|
||||||
|
ethcore-util = { path = "../../util" }
|
||||||
|
log = "0.3"
|
||||||
|
parity-wasm = "0.12"
|
||||||
|
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
|
||||||
|
vm = { path = "../vm" }
|
||||||
|
ethcore-logger = { path = "../../logger" }
|
@ -86,6 +86,20 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
|||||||
&[],
|
&[],
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
Static(
|
||||||
|
"abortOnCannotGrowMemory",
|
||||||
|
&[I32; 0],
|
||||||
|
Some(I32)
|
||||||
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
THIS IS EXPERIMENTAL RUST-ONLY RUNTIME EXTERNS, THEY ARE SUBJECT TO CHANGE
|
||||||
|
|
||||||
|
AVOID YOUR WASM CONTAINS ANY OF THESE OTHERWISE
|
||||||
|
EITHER FACE THE NEED OF HARDFORK
|
||||||
|
OR YOU CAN STUCK ON SPECIFIC RUST VERSION FOR WASM COMPILATION
|
||||||
|
*/
|
||||||
|
|
||||||
Static(
|
Static(
|
||||||
"_rust_begin_unwind",
|
"_rust_begin_unwind",
|
||||||
&[I32; 4],
|
&[I32; 4],
|
||||||
@ -121,4 +135,9 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
|||||||
&[I32; 0],
|
&[I32; 0],
|
||||||
None
|
None
|
||||||
),
|
),
|
||||||
|
Static(
|
||||||
|
"___setErrNo",
|
||||||
|
&[I32; 1],
|
||||||
|
None
|
||||||
|
),
|
||||||
];
|
];
|
@ -16,6 +16,14 @@
|
|||||||
|
|
||||||
//! Wasm Interpreter
|
//! Wasm Interpreter
|
||||||
|
|
||||||
|
extern crate vm;
|
||||||
|
extern crate ethcore_util as util;
|
||||||
|
#[macro_use] extern crate log;
|
||||||
|
extern crate ethcore_logger;
|
||||||
|
extern crate byteorder;
|
||||||
|
extern crate parity_wasm;
|
||||||
|
extern crate wasm_utils;
|
||||||
|
|
||||||
mod runtime;
|
mod runtime;
|
||||||
mod ptr;
|
mod ptr;
|
||||||
mod call_args;
|
mod call_args;
|
||||||
@ -30,10 +38,8 @@ const DEFAULT_STACK_SPACE: u32 = 5 * 1024 * 1024;
|
|||||||
|
|
||||||
use parity_wasm::{interpreter, elements};
|
use parity_wasm::{interpreter, elements};
|
||||||
use parity_wasm::interpreter::ModuleInstanceInterface;
|
use parity_wasm::interpreter::ModuleInstanceInterface;
|
||||||
use wasm_utils;
|
|
||||||
|
|
||||||
use evm::{self, GasLeft, ReturnData};
|
use vm::{GasLeft, ReturnData, ActionParams};
|
||||||
use action_params::ActionParams;
|
|
||||||
use self::runtime::{Runtime, RuntimeContext};
|
use self::runtime::{Runtime, RuntimeContext};
|
||||||
|
|
||||||
pub use self::runtime::Error as RuntimeError;
|
pub use self::runtime::Error as RuntimeError;
|
||||||
@ -56,9 +62,9 @@ impl WasmInterpreter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl evm::Evm for WasmInterpreter {
|
impl vm::Vm for WasmInterpreter {
|
||||||
|
|
||||||
fn exec(&mut self, params: ActionParams, ext: &mut ::ext::Ext) -> evm::Result<GasLeft> {
|
fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
|
||||||
use parity_wasm::elements::Deserialize;
|
use parity_wasm::elements::Deserialize;
|
||||||
|
|
||||||
let code = params.code.expect("exec is only called on contract with code; qed");
|
let code = params.code.expect("exec is only called on contract with code; qed");
|
||||||
@ -74,7 +80,7 @@ impl evm::Evm for WasmInterpreter {
|
|||||||
.expect("Linear memory to exist in wasm runtime");
|
.expect("Linear memory to exist in wasm runtime");
|
||||||
|
|
||||||
if params.gas > ::std::u64::MAX.into() {
|
if params.gas > ::std::u64::MAX.into() {
|
||||||
return Err(evm::Error::Wasm("Wasm interpreter cannot run contracts with gas >= 2^64".to_owned()));
|
return Err(vm::Error::Wasm("Wasm interpreter cannot run contracts with gas >= 2^64".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut runtime = Runtime::with_params(
|
let mut runtime = Runtime::with_params(
|
||||||
@ -91,7 +97,7 @@ impl evm::Evm for WasmInterpreter {
|
|||||||
elements::Module::deserialize(
|
elements::Module::deserialize(
|
||||||
&mut cursor
|
&mut cursor
|
||||||
).map_err(|err| {
|
).map_err(|err| {
|
||||||
evm::Error::Wasm(format!("Error deserializing contract code ({:?})", err))
|
vm::Error::Wasm(format!("Error deserializing contract code ({:?})", err))
|
||||||
})?
|
})?
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -112,7 +118,7 @@ impl evm::Evm for WasmInterpreter {
|
|||||||
interpreter::env_native_module(env_instance, native_bindings(&mut runtime))
|
interpreter::env_native_module(env_instance, native_bindings(&mut runtime))
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
// todo: prefer explicit panic here also?
|
// todo: prefer explicit panic here also?
|
||||||
evm::Error::Wasm(format!("Error instantiating native bindings: {:?}", err))
|
vm::Error::Wasm(format!("Error instantiating native bindings: {:?}", err))
|
||||||
})?
|
})?
|
||||||
)
|
)
|
||||||
).add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32));
|
).add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32));
|
||||||
@ -120,13 +126,13 @@ impl evm::Evm for WasmInterpreter {
|
|||||||
let module_instance = self.program.add_module("contract", contract_module, Some(&execution_params.externals))
|
let module_instance = self.program.add_module("contract", contract_module, Some(&execution_params.externals))
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
trace!(target: "wasm", "Error adding contract module: {:?}", err);
|
trace!(target: "wasm", "Error adding contract module: {:?}", err);
|
||||||
evm::Error::from(RuntimeError::Interpreter(err))
|
vm::Error::from(RuntimeError::Interpreter(err))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
module_instance.execute_export("_call", execution_params)
|
module_instance.execute_export("_call", execution_params)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
trace!(target: "wasm", "Error executing contract: {:?}", err);
|
trace!(target: "wasm", "Error executing contract: {:?}", err);
|
||||||
evm::Error::from(RuntimeError::Interpreter(err))
|
vm::Error::from(RuntimeError::Interpreter(err))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,3 +164,9 @@ fn native_bindings<'a>(runtime: &'a mut Runtime) -> interpreter::UserFunctions<'
|
|||||||
functions: ::std::borrow::Cow::from(env::SIGNATURES),
|
functions: ::std::borrow::Cow::from(env::SIGNATURES),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<runtime::Error> for vm::Error {
|
||||||
|
fn from(err: runtime::Error) -> vm::Error {
|
||||||
|
vm::Error::Wasm(format!("WASM runtime-error: {:?}", err))
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user